2011-02-11 16:09:10 +03:00
# include <linux/slab.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/device.h>
# include <linux/workqueue.h>
# include <linux/kfifo.h>
# include <linux/mutex.h>
2012-04-25 18:54:58 +04:00
# include <linux/iio/kfifo_buf.h>
2012-06-30 16:52:00 +04:00
# include <linux/sched.h>
2013-09-15 19:31:00 +04:00
# include <linux/poll.h>
2011-02-11 16:09:10 +03:00
2011-08-30 15:32:43 +04:00
struct iio_kfifo {
2011-09-21 14:15:57 +04:00
struct iio_buffer buffer ;
2011-08-30 15:32:43 +04:00
struct kfifo kf ;
2013-10-15 12:30:00 +04:00
struct mutex user_lock ;
2011-08-30 15:32:43 +04:00
int update_needed ;
} ;
2011-09-21 14:15:57 +04:00
# define iio_to_kfifo(r) container_of(r, struct iio_kfifo, buffer)
2011-05-18 17:42:24 +04:00
2011-02-11 16:09:10 +03:00
static inline int __iio_allocate_kfifo ( struct iio_kfifo * buf ,
int bytes_per_datum , int length )
{
if ( ( length = = 0 ) | | ( bytes_per_datum = = 0 ) )
return - EINVAL ;
2012-06-30 16:52:00 +04:00
return __kfifo_alloc ( ( struct __kfifo * ) & buf - > kf , length ,
bytes_per_datum , GFP_KERNEL ) ;
2011-02-11 16:09:10 +03:00
}
2011-09-21 14:15:57 +04:00
static int iio_request_update_kfifo ( struct iio_buffer * r )
2011-02-11 16:09:10 +03:00
{
int ret = 0 ;
struct iio_kfifo * buf = iio_to_kfifo ( r ) ;
2013-10-15 12:30:00 +04:00
mutex_lock ( & buf - > user_lock ) ;
2013-10-15 12:30:00 +04:00
if ( buf - > update_needed ) {
kfifo_free ( & buf - > kf ) ;
ret = __iio_allocate_kfifo ( buf , buf - > buffer . bytes_per_datum ,
2011-09-21 14:15:57 +04:00
buf - > buffer . length ) ;
2013-10-15 12:30:00 +04:00
buf - > update_needed = false ;
2013-10-15 12:30:00 +04:00
} else {
kfifo_reset_out ( & buf - > kf ) ;
}
2013-10-15 12:30:00 +04:00
mutex_unlock ( & buf - > user_lock ) ;
2013-10-15 12:30:00 +04:00
2011-02-11 16:09:10 +03:00
return ret ;
}
2011-12-19 18:23:48 +04:00
static int iio_mark_update_needed_kfifo ( struct iio_buffer * r )
2011-02-11 16:09:10 +03:00
{
2011-12-19 18:23:48 +04:00
struct iio_kfifo * kf = iio_to_kfifo ( r ) ;
kf - > update_needed = true ;
2011-02-11 16:09:10 +03:00
return 0 ;
}
2011-12-19 18:23:48 +04:00
static int iio_set_bytes_per_datum_kfifo ( struct iio_buffer * r , size_t bpd )
2011-02-11 16:09:10 +03:00
{
2011-12-19 18:23:48 +04:00
if ( r - > bytes_per_datum ! = bpd ) {
r - > bytes_per_datum = bpd ;
iio_mark_update_needed_kfifo ( r ) ;
}
2011-02-11 16:09:10 +03:00
return 0 ;
}
2011-09-21 14:15:57 +04:00
static int iio_set_length_kfifo ( struct iio_buffer * r , int length )
2011-02-11 16:09:10 +03:00
{
2012-06-30 16:52:00 +04:00
/* Avoid an invalid state */
if ( length < 2 )
length = 2 ;
2011-02-11 16:09:10 +03:00
if ( r - > length ! = length ) {
r - > length = length ;
2011-12-19 18:23:48 +04:00
iio_mark_update_needed_kfifo ( r ) ;
2011-02-11 16:09:10 +03:00
}
return 0 ;
}
2011-09-21 14:15:57 +04:00
static int iio_store_to_kfifo ( struct iio_buffer * r ,
2013-09-15 20:50:00 +04:00
const void * data )
2011-02-11 16:09:10 +03:00
{
int ret ;
struct iio_kfifo * kf = iio_to_kfifo ( r ) ;
2012-06-30 16:52:00 +04:00
ret = kfifo_in ( & kf - > kf , data , 1 ) ;
if ( ret ! = 1 )
2011-02-11 16:09:10 +03:00
return - EBUSY ;
2013-11-25 18:56:00 +04:00
2013-09-15 19:31:00 +04:00
wake_up_interruptible_poll ( & r - > pollq , POLLIN | POLLRDNORM ) ;
2012-06-30 16:52:00 +04:00
2011-02-11 16:09:10 +03:00
return 0 ;
}
2011-09-21 14:15:57 +04:00
static int iio_read_first_n_kfifo ( struct iio_buffer * r ,
2011-05-18 17:41:02 +04:00
size_t n , char __user * buf )
2011-02-11 16:09:10 +03:00
{
int ret , copied ;
struct iio_kfifo * kf = iio_to_kfifo ( r ) ;
2013-10-15 12:30:00 +04:00
if ( mutex_lock_interruptible ( & kf - > user_lock ) )
return - ERESTARTSYS ;
2011-12-12 12:33:14 +04:00
2013-10-15 12:30:00 +04:00
if ( ! kfifo_initialized ( & kf - > kf ) | | n < kfifo_esize ( & kf - > kf ) )
ret = - EINVAL ;
else
ret = kfifo_to_user ( & kf - > kf , buf , n , & copied ) ;
mutex_unlock ( & kf - > user_lock ) ;
if ( ret < 0 )
return ret ;
2011-02-11 16:09:10 +03:00
return copied ;
}
2011-05-18 17:42:24 +04:00
2013-11-25 18:56:00 +04:00
static bool iio_kfifo_buf_data_available ( struct iio_buffer * r )
{
struct iio_kfifo * kf = iio_to_kfifo ( r ) ;
bool empty ;
mutex_lock ( & kf - > user_lock ) ;
empty = kfifo_is_empty ( & kf - > kf ) ;
mutex_unlock ( & kf - > user_lock ) ;
return ! empty ;
}
2013-10-04 15:06:00 +04:00
static void iio_kfifo_buffer_release ( struct iio_buffer * buffer )
{
2013-10-15 12:30:00 +04:00
struct iio_kfifo * kf = iio_to_kfifo ( buffer ) ;
2013-10-15 12:30:00 +04:00
mutex_destroy ( & kf - > user_lock ) ;
2013-10-15 12:30:00 +04:00
kfifo_free ( & kf - > kf ) ;
kfree ( kf ) ;
2013-10-04 15:06:00 +04:00
}
2012-01-03 14:02:51 +04:00
static const struct iio_buffer_access_funcs kfifo_access_funcs = {
2011-05-18 17:42:24 +04:00
. store_to = & iio_store_to_kfifo ,
. read_first_n = & iio_read_first_n_kfifo ,
2013-11-25 18:56:00 +04:00
. data_available = iio_kfifo_buf_data_available ,
2011-05-18 17:42:24 +04:00
. request_update = & iio_request_update_kfifo ,
. set_bytes_per_datum = & iio_set_bytes_per_datum_kfifo ,
. set_length = & iio_set_length_kfifo ,
2013-10-04 15:06:00 +04:00
. release = & iio_kfifo_buffer_release ,
2011-05-18 17:42:24 +04:00
} ;
2012-01-03 14:02:51 +04:00
2014-12-19 20:39:24 +03:00
struct iio_buffer * iio_kfifo_allocate ( void )
2012-01-03 14:02:51 +04:00
{
struct iio_kfifo * kf ;
2014-12-19 20:39:24 +03:00
kf = kzalloc ( sizeof ( * kf ) , GFP_KERNEL ) ;
2012-01-03 14:02:51 +04:00
if ( ! kf )
return NULL ;
2014-12-19 20:39:24 +03:00
2012-01-03 14:02:51 +04:00
kf - > update_needed = true ;
iio_buffer_init ( & kf - > buffer ) ;
kf - > buffer . access = & kfifo_access_funcs ;
2012-06-30 16:52:00 +04:00
kf - > buffer . length = 2 ;
2013-10-15 12:30:00 +04:00
mutex_init ( & kf - > user_lock ) ;
2014-12-19 20:39:24 +03:00
2012-01-03 14:02:51 +04:00
return & kf - > buffer ;
}
EXPORT_SYMBOL ( iio_kfifo_allocate ) ;
void iio_kfifo_free ( struct iio_buffer * r )
{
2013-10-04 15:06:00 +04:00
iio_buffer_put ( r ) ;
2012-01-03 14:02:51 +04:00
}
EXPORT_SYMBOL ( iio_kfifo_free ) ;
2011-05-18 17:42:24 +04:00
2014-12-19 20:39:25 +03:00
static void devm_iio_kfifo_release ( struct device * dev , void * res )
{
iio_kfifo_free ( * ( struct iio_buffer * * ) res ) ;
}
static int devm_iio_kfifo_match ( struct device * dev , void * res , void * data )
{
struct iio_buffer * * r = res ;
if ( WARN_ON ( ! r | | ! * r ) )
return 0 ;
return * r = = data ;
}
/**
* devm_iio_fifo_allocate - Resource - managed iio_kfifo_allocate ( )
* @ dev : Device to allocate kfifo buffer for
*
* RETURNS :
* Pointer to allocated iio_buffer on success , NULL on failure .
*/
struct iio_buffer * devm_iio_kfifo_allocate ( struct device * dev )
{
struct iio_buffer * * ptr , * r ;
ptr = devres_alloc ( devm_iio_kfifo_release , sizeof ( * ptr ) , GFP_KERNEL ) ;
if ( ! ptr )
return NULL ;
r = iio_kfifo_allocate ( ) ;
if ( r ) {
* ptr = r ;
devres_add ( dev , ptr ) ;
} else {
devres_free ( ptr ) ;
}
return r ;
}
EXPORT_SYMBOL ( devm_iio_kfifo_allocate ) ;
/**
* devm_iio_fifo_free - Resource - managed iio_kfifo_free ( )
* @ dev : Device the buffer belongs to
* @ r : The buffer associated with the device
*/
void devm_iio_kfifo_free ( struct device * dev , struct iio_buffer * r )
{
WARN_ON ( devres_release ( dev , devm_iio_kfifo_release ,
devm_iio_kfifo_match , r ) ) ;
}
EXPORT_SYMBOL ( devm_iio_kfifo_free ) ;
2011-02-11 16:09:10 +03:00
MODULE_LICENSE ( " GPL " ) ;