2009-03-21 23:31:23 +03:00
/*
* Copyright ( c ) 2007 - 2009 Intel Corporation . All rights reserved .
*
* 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 ; either version 2 of the License , or ( at your option )
* any later version .
*
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License along with
* this program ; if not , write to the Free Software Foundation , Inc . , 59
* Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*
* The full GNU General Public License is included in this distribution in the
* file called COPYING .
*/
2007-10-16 12:27:41 +04:00
# include <linux/kernel.h>
# include <linux/spinlock.h>
# include <linux/device.h>
# include <linux/idr.h>
# include <linux/kdev_t.h>
# include <linux/err.h>
# include <linux/dca.h>
static struct class * dca_class ;
static struct idr dca_idr ;
static spinlock_t dca_idr_lock ;
int dca_sysfs_add_req ( struct dca_provider * dca , struct device * dev , int slot )
{
2008-02-09 02:00:49 +03:00
struct device * cd ;
2008-07-23 04:30:57 +04:00
static int req_count ;
2007-10-16 12:27:41 +04:00
2008-07-22 07:03:34 +04:00
cd = device_create ( dca_class , dca - > cd , MKDEV ( 0 , slot + 1 ) , NULL ,
" requester%d " , req_count + + ) ;
2007-10-16 12:27:41 +04:00
if ( IS_ERR ( cd ) )
return PTR_ERR ( cd ) ;
return 0 ;
}
void dca_sysfs_remove_req ( struct dca_provider * dca , int slot )
{
2008-02-09 02:00:49 +03:00
device_destroy ( dca_class , MKDEV ( 0 , slot + 1 ) ) ;
2007-10-16 12:27:41 +04:00
}
int dca_sysfs_add_provider ( struct dca_provider * dca , struct device * dev )
{
2008-02-09 02:00:49 +03:00
struct device * cd ;
2007-10-16 12:27:41 +04:00
int err = 0 ;
idr_try_again :
if ( ! idr_pre_get ( & dca_idr , GFP_KERNEL ) )
return - ENOMEM ;
spin_lock ( & dca_idr_lock ) ;
err = idr_get_new ( & dca_idr , dca , & dca - > id ) ;
spin_unlock ( & dca_idr_lock ) ;
switch ( err ) {
case 0 :
break ;
case - EAGAIN :
goto idr_try_again ;
default :
return err ;
}
2008-07-22 07:03:34 +04:00
cd = device_create ( dca_class , dev , MKDEV ( 0 , 0 ) , NULL , " dca%d " , dca - > id ) ;
2007-10-16 12:27:41 +04:00
if ( IS_ERR ( cd ) ) {
spin_lock ( & dca_idr_lock ) ;
idr_remove ( & dca_idr , dca - > id ) ;
spin_unlock ( & dca_idr_lock ) ;
return PTR_ERR ( cd ) ;
}
dca - > cd = cd ;
return 0 ;
}
void dca_sysfs_remove_provider ( struct dca_provider * dca )
{
2008-02-09 02:00:49 +03:00
device_unregister ( dca - > cd ) ;
2007-10-16 12:27:41 +04:00
dca - > cd = NULL ;
spin_lock ( & dca_idr_lock ) ;
idr_remove ( & dca_idr , dca - > id ) ;
spin_unlock ( & dca_idr_lock ) ;
}
int __init dca_sysfs_init ( void )
{
idr_init ( & dca_idr ) ;
spin_lock_init ( & dca_idr_lock ) ;
dca_class = class_create ( THIS_MODULE , " dca " ) ;
if ( IS_ERR ( dca_class ) ) {
idr_destroy ( & dca_idr ) ;
return PTR_ERR ( dca_class ) ;
}
return 0 ;
}
void __exit dca_sysfs_exit ( void )
{
class_destroy ( dca_class ) ;
idr_destroy ( & dca_idr ) ;
}