2005-04-17 02:20:36 +04:00
/*
kfifo: move struct kfifo in place
This is a new generic kernel FIFO implementation.
The current kernel fifo API is not very widely used, because it has to
many constrains. Only 17 files in the current 2.6.31-rc5 used it.
FIFO's are like list's a very basic thing and a kfifo API which handles
the most use case would save a lot of development time and memory
resources.
I think this are the reasons why kfifo is not in use:
- The API is to simple, important functions are missing
- A fifo can be only allocated dynamically
- There is a requirement of a spinlock whether you need it or not
- There is no support for data records inside a fifo
So I decided to extend the kfifo in a more generic way without blowing up
the API to much. The new API has the following benefits:
- Generic usage: For kernel internal use and/or device driver.
- Provide an API for the most use case.
- Slim API: The whole API provides 25 functions.
- Linux style habit.
- DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros
- Direct copy_to_user from the fifo and copy_from_user into the fifo.
- The kfifo itself is an in place member of the using data structure, this save an
indirection access and does not waste the kernel allocator.
- Lockless access: if only one reader and one writer is active on the fifo,
which is the common use case, no additional locking is necessary.
- Remove spinlock - give the user the freedom of choice what kind of locking to use if
one is required.
- Ability to handle records. Three type of records are supported:
- Variable length records between 0-255 bytes, with a record size
field of 1 bytes.
- Variable length records between 0-65535 bytes, with a record size
field of 2 bytes.
- Fixed size records, which no record size field.
- Preserve memory resource.
- Performance!
- Easy to use!
This patch:
Since most users want to have the kfifo as part of another object,
reorganize the code to allow including struct kfifo in another data
structure. This requires changing the kfifo_alloc and kfifo_init
prototypes so that we pass an existing kfifo pointer into them. This
patch changes the implementation and all existing users.
[akpm@linux-foundation.org: fix warning]
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-12-22 01:37:26 +03:00
* A generic kernel FIFO implementation .
2005-04-17 02:20:36 +04:00
*
kfifo: move struct kfifo in place
This is a new generic kernel FIFO implementation.
The current kernel fifo API is not very widely used, because it has to
many constrains. Only 17 files in the current 2.6.31-rc5 used it.
FIFO's are like list's a very basic thing and a kfifo API which handles
the most use case would save a lot of development time and memory
resources.
I think this are the reasons why kfifo is not in use:
- The API is to simple, important functions are missing
- A fifo can be only allocated dynamically
- There is a requirement of a spinlock whether you need it or not
- There is no support for data records inside a fifo
So I decided to extend the kfifo in a more generic way without blowing up
the API to much. The new API has the following benefits:
- Generic usage: For kernel internal use and/or device driver.
- Provide an API for the most use case.
- Slim API: The whole API provides 25 functions.
- Linux style habit.
- DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros
- Direct copy_to_user from the fifo and copy_from_user into the fifo.
- The kfifo itself is an in place member of the using data structure, this save an
indirection access and does not waste the kernel allocator.
- Lockless access: if only one reader and one writer is active on the fifo,
which is the common use case, no additional locking is necessary.
- Remove spinlock - give the user the freedom of choice what kind of locking to use if
one is required.
- Ability to handle records. Three type of records are supported:
- Variable length records between 0-255 bytes, with a record size
field of 1 bytes.
- Variable length records between 0-65535 bytes, with a record size
field of 2 bytes.
- Fixed size records, which no record size field.
- Preserve memory resource.
- Performance!
- Easy to use!
This patch:
Since most users want to have the kfifo as part of another object,
reorganize the code to allow including struct kfifo in another data
structure. This requires changing the kfifo_alloc and kfifo_init
prototypes so that we pass an existing kfifo pointer into them. This
patch changes the implementation and all existing users.
[akpm@linux-foundation.org: fix warning]
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-12-22 01:37:26 +03:00
* Copyright ( C ) 2009 Stefani Seibold < stefani @ seibold . net >
2005-04-17 02:20:36 +04:00
* Copyright ( C ) 2004 Stelian Pop < stelian @ popies . net >
*
* 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 . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/err.h>
# include <linux/kfifo.h>
2007-07-16 10:41:34 +04:00
# include <linux/log2.h>
2009-12-22 01:37:31 +03:00
# include <linux/uaccess.h>
2005-04-17 02:20:36 +04:00
2010-01-16 04:01:12 +03:00
static void _kfifo_init ( struct kfifo * fifo , void * buffer ,
2009-12-22 01:37:27 +03:00
unsigned int size )
kfifo: move struct kfifo in place
This is a new generic kernel FIFO implementation.
The current kernel fifo API is not very widely used, because it has to
many constrains. Only 17 files in the current 2.6.31-rc5 used it.
FIFO's are like list's a very basic thing and a kfifo API which handles
the most use case would save a lot of development time and memory
resources.
I think this are the reasons why kfifo is not in use:
- The API is to simple, important functions are missing
- A fifo can be only allocated dynamically
- There is a requirement of a spinlock whether you need it or not
- There is no support for data records inside a fifo
So I decided to extend the kfifo in a more generic way without blowing up
the API to much. The new API has the following benefits:
- Generic usage: For kernel internal use and/or device driver.
- Provide an API for the most use case.
- Slim API: The whole API provides 25 functions.
- Linux style habit.
- DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros
- Direct copy_to_user from the fifo and copy_from_user into the fifo.
- The kfifo itself is an in place member of the using data structure, this save an
indirection access and does not waste the kernel allocator.
- Lockless access: if only one reader and one writer is active on the fifo,
which is the common use case, no additional locking is necessary.
- Remove spinlock - give the user the freedom of choice what kind of locking to use if
one is required.
- Ability to handle records. Three type of records are supported:
- Variable length records between 0-255 bytes, with a record size
field of 1 bytes.
- Variable length records between 0-65535 bytes, with a record size
field of 2 bytes.
- Fixed size records, which no record size field.
- Preserve memory resource.
- Performance!
- Easy to use!
This patch:
Since most users want to have the kfifo as part of another object,
reorganize the code to allow including struct kfifo in another data
structure. This requires changing the kfifo_alloc and kfifo_init
prototypes so that we pass an existing kfifo pointer into them. This
patch changes the implementation and all existing users.
[akpm@linux-foundation.org: fix warning]
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-12-22 01:37:26 +03:00
{
fifo - > buffer = buffer ;
fifo - > size = size ;
kfifo_reset ( fifo ) ;
}
2005-04-17 02:20:36 +04:00
/**
kfifo: move struct kfifo in place
This is a new generic kernel FIFO implementation.
The current kernel fifo API is not very widely used, because it has to
many constrains. Only 17 files in the current 2.6.31-rc5 used it.
FIFO's are like list's a very basic thing and a kfifo API which handles
the most use case would save a lot of development time and memory
resources.
I think this are the reasons why kfifo is not in use:
- The API is to simple, important functions are missing
- A fifo can be only allocated dynamically
- There is a requirement of a spinlock whether you need it or not
- There is no support for data records inside a fifo
So I decided to extend the kfifo in a more generic way without blowing up
the API to much. The new API has the following benefits:
- Generic usage: For kernel internal use and/or device driver.
- Provide an API for the most use case.
- Slim API: The whole API provides 25 functions.
- Linux style habit.
- DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros
- Direct copy_to_user from the fifo and copy_from_user into the fifo.
- The kfifo itself is an in place member of the using data structure, this save an
indirection access and does not waste the kernel allocator.
- Lockless access: if only one reader and one writer is active on the fifo,
which is the common use case, no additional locking is necessary.
- Remove spinlock - give the user the freedom of choice what kind of locking to use if
one is required.
- Ability to handle records. Three type of records are supported:
- Variable length records between 0-255 bytes, with a record size
field of 1 bytes.
- Variable length records between 0-65535 bytes, with a record size
field of 2 bytes.
- Fixed size records, which no record size field.
- Preserve memory resource.
- Performance!
- Easy to use!
This patch:
Since most users want to have the kfifo as part of another object,
reorganize the code to allow including struct kfifo in another data
structure. This requires changing the kfifo_alloc and kfifo_init
prototypes so that we pass an existing kfifo pointer into them. This
patch changes the implementation and all existing users.
[akpm@linux-foundation.org: fix warning]
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-12-22 01:37:26 +03:00
* kfifo_init - initialize a FIFO using a preallocated buffer
* @ fifo : the fifo to assign the buffer
2005-04-17 02:20:36 +04:00
* @ buffer : the preallocated buffer to be used .
* @ size : the size of the internal buffer , this have to be a power of 2.
*
*/
2010-01-16 04:01:12 +03:00
void kfifo_init ( struct kfifo * fifo , void * buffer , unsigned int size )
2005-04-17 02:20:36 +04:00
{
/* size must be a power of 2 */
2007-07-16 10:41:34 +04:00
BUG_ON ( ! is_power_of_2 ( size ) ) ;
2005-04-17 02:20:36 +04:00
2009-12-22 01:37:27 +03:00
_kfifo_init ( fifo , buffer , size ) ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL ( kfifo_init ) ;
/**
kfifo: move struct kfifo in place
This is a new generic kernel FIFO implementation.
The current kernel fifo API is not very widely used, because it has to
many constrains. Only 17 files in the current 2.6.31-rc5 used it.
FIFO's are like list's a very basic thing and a kfifo API which handles
the most use case would save a lot of development time and memory
resources.
I think this are the reasons why kfifo is not in use:
- The API is to simple, important functions are missing
- A fifo can be only allocated dynamically
- There is a requirement of a spinlock whether you need it or not
- There is no support for data records inside a fifo
So I decided to extend the kfifo in a more generic way without blowing up
the API to much. The new API has the following benefits:
- Generic usage: For kernel internal use and/or device driver.
- Provide an API for the most use case.
- Slim API: The whole API provides 25 functions.
- Linux style habit.
- DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros
- Direct copy_to_user from the fifo and copy_from_user into the fifo.
- The kfifo itself is an in place member of the using data structure, this save an
indirection access and does not waste the kernel allocator.
- Lockless access: if only one reader and one writer is active on the fifo,
which is the common use case, no additional locking is necessary.
- Remove spinlock - give the user the freedom of choice what kind of locking to use if
one is required.
- Ability to handle records. Three type of records are supported:
- Variable length records between 0-255 bytes, with a record size
field of 1 bytes.
- Variable length records between 0-65535 bytes, with a record size
field of 2 bytes.
- Fixed size records, which no record size field.
- Preserve memory resource.
- Performance!
- Easy to use!
This patch:
Since most users want to have the kfifo as part of another object,
reorganize the code to allow including struct kfifo in another data
structure. This requires changing the kfifo_alloc and kfifo_init
prototypes so that we pass an existing kfifo pointer into them. This
patch changes the implementation and all existing users.
[akpm@linux-foundation.org: fix warning]
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-12-22 01:37:26 +03:00
* kfifo_alloc - allocates a new FIFO internal buffer
* @ fifo : the fifo to assign then new buffer
* @ size : the size of the buffer to be allocated , this have to be a power of 2.
2005-04-17 02:20:36 +04:00
* @ gfp_mask : get_free_pages mask , passed to kmalloc ( )
*
kfifo: move struct kfifo in place
This is a new generic kernel FIFO implementation.
The current kernel fifo API is not very widely used, because it has to
many constrains. Only 17 files in the current 2.6.31-rc5 used it.
FIFO's are like list's a very basic thing and a kfifo API which handles
the most use case would save a lot of development time and memory
resources.
I think this are the reasons why kfifo is not in use:
- The API is to simple, important functions are missing
- A fifo can be only allocated dynamically
- There is a requirement of a spinlock whether you need it or not
- There is no support for data records inside a fifo
So I decided to extend the kfifo in a more generic way without blowing up
the API to much. The new API has the following benefits:
- Generic usage: For kernel internal use and/or device driver.
- Provide an API for the most use case.
- Slim API: The whole API provides 25 functions.
- Linux style habit.
- DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros
- Direct copy_to_user from the fifo and copy_from_user into the fifo.
- The kfifo itself is an in place member of the using data structure, this save an
indirection access and does not waste the kernel allocator.
- Lockless access: if only one reader and one writer is active on the fifo,
which is the common use case, no additional locking is necessary.
- Remove spinlock - give the user the freedom of choice what kind of locking to use if
one is required.
- Ability to handle records. Three type of records are supported:
- Variable length records between 0-255 bytes, with a record size
field of 1 bytes.
- Variable length records between 0-65535 bytes, with a record size
field of 2 bytes.
- Fixed size records, which no record size field.
- Preserve memory resource.
- Performance!
- Easy to use!
This patch:
Since most users want to have the kfifo as part of another object,
reorganize the code to allow including struct kfifo in another data
structure. This requires changing the kfifo_alloc and kfifo_init
prototypes so that we pass an existing kfifo pointer into them. This
patch changes the implementation and all existing users.
[akpm@linux-foundation.org: fix warning]
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-12-22 01:37:26 +03:00
* This function dynamically allocates a new fifo internal buffer
*
2005-04-17 02:20:36 +04:00
* The size will be rounded - up to a power of 2.
kfifo: move struct kfifo in place
This is a new generic kernel FIFO implementation.
The current kernel fifo API is not very widely used, because it has to
many constrains. Only 17 files in the current 2.6.31-rc5 used it.
FIFO's are like list's a very basic thing and a kfifo API which handles
the most use case would save a lot of development time and memory
resources.
I think this are the reasons why kfifo is not in use:
- The API is to simple, important functions are missing
- A fifo can be only allocated dynamically
- There is a requirement of a spinlock whether you need it or not
- There is no support for data records inside a fifo
So I decided to extend the kfifo in a more generic way without blowing up
the API to much. The new API has the following benefits:
- Generic usage: For kernel internal use and/or device driver.
- Provide an API for the most use case.
- Slim API: The whole API provides 25 functions.
- Linux style habit.
- DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros
- Direct copy_to_user from the fifo and copy_from_user into the fifo.
- The kfifo itself is an in place member of the using data structure, this save an
indirection access and does not waste the kernel allocator.
- Lockless access: if only one reader and one writer is active on the fifo,
which is the common use case, no additional locking is necessary.
- Remove spinlock - give the user the freedom of choice what kind of locking to use if
one is required.
- Ability to handle records. Three type of records are supported:
- Variable length records between 0-255 bytes, with a record size
field of 1 bytes.
- Variable length records between 0-65535 bytes, with a record size
field of 2 bytes.
- Fixed size records, which no record size field.
- Preserve memory resource.
- Performance!
- Easy to use!
This patch:
Since most users want to have the kfifo as part of another object,
reorganize the code to allow including struct kfifo in another data
structure. This requires changing the kfifo_alloc and kfifo_init
prototypes so that we pass an existing kfifo pointer into them. This
patch changes the implementation and all existing users.
[akpm@linux-foundation.org: fix warning]
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-12-22 01:37:26 +03:00
* The buffer will be release with kfifo_free ( ) .
* Return 0 if no error , otherwise the an error code
2005-04-17 02:20:36 +04:00
*/
2009-12-22 01:37:27 +03:00
int kfifo_alloc ( struct kfifo * fifo , unsigned int size , gfp_t gfp_mask )
2005-04-17 02:20:36 +04:00
{
unsigned char * buffer ;
/*
* round up to the next power of 2 , since our ' let the indices
2009-06-17 02:33:34 +04:00
* wrap ' technique works only in this case .
2005-04-17 02:20:36 +04:00
*/
2009-06-17 02:33:34 +04:00
if ( ! is_power_of_2 ( size ) ) {
2005-04-17 02:20:36 +04:00
BUG_ON ( size > 0x80000000 ) ;
size = roundup_pow_of_two ( size ) ;
}
buffer = kmalloc ( size , gfp_mask ) ;
kfifo: move struct kfifo in place
This is a new generic kernel FIFO implementation.
The current kernel fifo API is not very widely used, because it has to
many constrains. Only 17 files in the current 2.6.31-rc5 used it.
FIFO's are like list's a very basic thing and a kfifo API which handles
the most use case would save a lot of development time and memory
resources.
I think this are the reasons why kfifo is not in use:
- The API is to simple, important functions are missing
- A fifo can be only allocated dynamically
- There is a requirement of a spinlock whether you need it or not
- There is no support for data records inside a fifo
So I decided to extend the kfifo in a more generic way without blowing up
the API to much. The new API has the following benefits:
- Generic usage: For kernel internal use and/or device driver.
- Provide an API for the most use case.
- Slim API: The whole API provides 25 functions.
- Linux style habit.
- DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros
- Direct copy_to_user from the fifo and copy_from_user into the fifo.
- The kfifo itself is an in place member of the using data structure, this save an
indirection access and does not waste the kernel allocator.
- Lockless access: if only one reader and one writer is active on the fifo,
which is the common use case, no additional locking is necessary.
- Remove spinlock - give the user the freedom of choice what kind of locking to use if
one is required.
- Ability to handle records. Three type of records are supported:
- Variable length records between 0-255 bytes, with a record size
field of 1 bytes.
- Variable length records between 0-65535 bytes, with a record size
field of 2 bytes.
- Fixed size records, which no record size field.
- Preserve memory resource.
- Performance!
- Easy to use!
This patch:
Since most users want to have the kfifo as part of another object,
reorganize the code to allow including struct kfifo in another data
structure. This requires changing the kfifo_alloc and kfifo_init
prototypes so that we pass an existing kfifo pointer into them. This
patch changes the implementation and all existing users.
[akpm@linux-foundation.org: fix warning]
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-12-22 01:37:26 +03:00
if ( ! buffer ) {
2009-12-22 01:37:27 +03:00
_kfifo_init ( fifo , 0 , 0 ) ;
kfifo: move struct kfifo in place
This is a new generic kernel FIFO implementation.
The current kernel fifo API is not very widely used, because it has to
many constrains. Only 17 files in the current 2.6.31-rc5 used it.
FIFO's are like list's a very basic thing and a kfifo API which handles
the most use case would save a lot of development time and memory
resources.
I think this are the reasons why kfifo is not in use:
- The API is to simple, important functions are missing
- A fifo can be only allocated dynamically
- There is a requirement of a spinlock whether you need it or not
- There is no support for data records inside a fifo
So I decided to extend the kfifo in a more generic way without blowing up
the API to much. The new API has the following benefits:
- Generic usage: For kernel internal use and/or device driver.
- Provide an API for the most use case.
- Slim API: The whole API provides 25 functions.
- Linux style habit.
- DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros
- Direct copy_to_user from the fifo and copy_from_user into the fifo.
- The kfifo itself is an in place member of the using data structure, this save an
indirection access and does not waste the kernel allocator.
- Lockless access: if only one reader and one writer is active on the fifo,
which is the common use case, no additional locking is necessary.
- Remove spinlock - give the user the freedom of choice what kind of locking to use if
one is required.
- Ability to handle records. Three type of records are supported:
- Variable length records between 0-255 bytes, with a record size
field of 1 bytes.
- Variable length records between 0-65535 bytes, with a record size
field of 2 bytes.
- Fixed size records, which no record size field.
- Preserve memory resource.
- Performance!
- Easy to use!
This patch:
Since most users want to have the kfifo as part of another object,
reorganize the code to allow including struct kfifo in another data
structure. This requires changing the kfifo_alloc and kfifo_init
prototypes so that we pass an existing kfifo pointer into them. This
patch changes the implementation and all existing users.
[akpm@linux-foundation.org: fix warning]
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-12-22 01:37:26 +03:00
return - ENOMEM ;
}
2005-04-17 02:20:36 +04:00
2009-12-22 01:37:27 +03:00
_kfifo_init ( fifo , buffer , size ) ;
2005-04-17 02:20:36 +04:00
kfifo: move struct kfifo in place
This is a new generic kernel FIFO implementation.
The current kernel fifo API is not very widely used, because it has to
many constrains. Only 17 files in the current 2.6.31-rc5 used it.
FIFO's are like list's a very basic thing and a kfifo API which handles
the most use case would save a lot of development time and memory
resources.
I think this are the reasons why kfifo is not in use:
- The API is to simple, important functions are missing
- A fifo can be only allocated dynamically
- There is a requirement of a spinlock whether you need it or not
- There is no support for data records inside a fifo
So I decided to extend the kfifo in a more generic way without blowing up
the API to much. The new API has the following benefits:
- Generic usage: For kernel internal use and/or device driver.
- Provide an API for the most use case.
- Slim API: The whole API provides 25 functions.
- Linux style habit.
- DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros
- Direct copy_to_user from the fifo and copy_from_user into the fifo.
- The kfifo itself is an in place member of the using data structure, this save an
indirection access and does not waste the kernel allocator.
- Lockless access: if only one reader and one writer is active on the fifo,
which is the common use case, no additional locking is necessary.
- Remove spinlock - give the user the freedom of choice what kind of locking to use if
one is required.
- Ability to handle records. Three type of records are supported:
- Variable length records between 0-255 bytes, with a record size
field of 1 bytes.
- Variable length records between 0-65535 bytes, with a record size
field of 2 bytes.
- Fixed size records, which no record size field.
- Preserve memory resource.
- Performance!
- Easy to use!
This patch:
Since most users want to have the kfifo as part of another object,
reorganize the code to allow including struct kfifo in another data
structure. This requires changing the kfifo_alloc and kfifo_init
prototypes so that we pass an existing kfifo pointer into them. This
patch changes the implementation and all existing users.
[akpm@linux-foundation.org: fix warning]
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-12-22 01:37:26 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL ( kfifo_alloc ) ;
/**
kfifo: move struct kfifo in place
This is a new generic kernel FIFO implementation.
The current kernel fifo API is not very widely used, because it has to
many constrains. Only 17 files in the current 2.6.31-rc5 used it.
FIFO's are like list's a very basic thing and a kfifo API which handles
the most use case would save a lot of development time and memory
resources.
I think this are the reasons why kfifo is not in use:
- The API is to simple, important functions are missing
- A fifo can be only allocated dynamically
- There is a requirement of a spinlock whether you need it or not
- There is no support for data records inside a fifo
So I decided to extend the kfifo in a more generic way without blowing up
the API to much. The new API has the following benefits:
- Generic usage: For kernel internal use and/or device driver.
- Provide an API for the most use case.
- Slim API: The whole API provides 25 functions.
- Linux style habit.
- DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros
- Direct copy_to_user from the fifo and copy_from_user into the fifo.
- The kfifo itself is an in place member of the using data structure, this save an
indirection access and does not waste the kernel allocator.
- Lockless access: if only one reader and one writer is active on the fifo,
which is the common use case, no additional locking is necessary.
- Remove spinlock - give the user the freedom of choice what kind of locking to use if
one is required.
- Ability to handle records. Three type of records are supported:
- Variable length records between 0-255 bytes, with a record size
field of 1 bytes.
- Variable length records between 0-65535 bytes, with a record size
field of 2 bytes.
- Fixed size records, which no record size field.
- Preserve memory resource.
- Performance!
- Easy to use!
This patch:
Since most users want to have the kfifo as part of another object,
reorganize the code to allow including struct kfifo in another data
structure. This requires changing the kfifo_alloc and kfifo_init
prototypes so that we pass an existing kfifo pointer into them. This
patch changes the implementation and all existing users.
[akpm@linux-foundation.org: fix warning]
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-12-22 01:37:26 +03:00
* kfifo_free - frees the FIFO internal buffer
2005-04-17 02:20:36 +04:00
* @ fifo : the fifo to be freed .
*/
void kfifo_free ( struct kfifo * fifo )
{
kfree ( fifo - > buffer ) ;
}
EXPORT_SYMBOL ( kfifo_free ) ;
2009-12-22 01:37:31 +03:00
/**
* kfifo_skip - skip output data
* @ fifo : the fifo to be used .
* @ len : number of bytes to skip
*/
void kfifo_skip ( struct kfifo * fifo , unsigned int len )
{
if ( len < kfifo_len ( fifo ) ) {
__kfifo_add_out ( fifo , len ) ;
return ;
}
kfifo_reset_out ( fifo ) ;
}
EXPORT_SYMBOL ( kfifo_skip ) ;
2009-12-22 01:37:32 +03:00
static inline void __kfifo_in_data ( struct kfifo * fifo ,
const void * from , unsigned int len , unsigned int off )
2005-04-17 02:20:36 +04:00
{
unsigned int l ;
2006-09-29 13:00:11 +04:00
/*
* Ensure that we sample the fifo - > out index - before - we
* start putting bytes into the kfifo .
*/
smp_mb ( ) ;
2009-12-22 01:37:32 +03:00
off = __kfifo_off ( fifo , fifo - > in + off ) ;
2009-12-22 01:37:31 +03:00
2005-04-17 02:20:36 +04:00
/* first put the data starting from fifo->in to buffer end */
2009-12-22 01:37:31 +03:00
l = min ( len , fifo - > size - off ) ;
memcpy ( fifo - > buffer + off , from , l ) ;
2005-04-17 02:20:36 +04:00
/* then put the rest (if any) at the beginning of the buffer */
2009-12-22 01:37:28 +03:00
memcpy ( fifo - > buffer , from + l , len - l ) ;
2005-04-17 02:20:36 +04:00
}
2009-12-22 01:37:32 +03:00
static inline void __kfifo_out_data ( struct kfifo * fifo ,
void * to , unsigned int len , unsigned int off )
2005-04-17 02:20:36 +04:00
{
unsigned int l ;
2006-09-29 13:00:11 +04:00
/*
* Ensure that we sample the fifo - > in index - before - we
* start removing bytes from the kfifo .
*/
smp_rmb ( ) ;
2009-12-22 01:37:32 +03:00
off = __kfifo_off ( fifo , fifo - > out + off ) ;
2009-12-22 01:37:31 +03:00
2005-04-17 02:20:36 +04:00
/* first get the data from fifo->out until the end of the buffer */
2009-12-22 01:37:31 +03:00
l = min ( len , fifo - > size - off ) ;
memcpy ( to , fifo - > buffer + off , l ) ;
2005-04-17 02:20:36 +04:00
/* then get the rest (if any) from the beginning of the buffer */
2009-12-22 01:37:28 +03:00
memcpy ( to + l , fifo - > buffer , len - l ) ;
2009-12-22 01:37:31 +03:00
}
2010-01-16 04:01:15 +03:00
static inline int __kfifo_from_user_data ( struct kfifo * fifo ,
const void __user * from , unsigned int len , unsigned int off ,
unsigned * lenout )
2009-12-22 01:37:31 +03:00
{
unsigned int l ;
int ret ;
2006-09-29 13:00:11 +04:00
/*
2009-12-22 01:37:31 +03:00
* Ensure that we sample the fifo - > out index - before - we
* start putting bytes into the kfifo .
2006-09-29 13:00:11 +04:00
*/
smp_mb ( ) ;
2009-12-22 01:37:32 +03:00
off = __kfifo_off ( fifo , fifo - > in + off ) ;
2009-12-22 01:37:31 +03:00
/* first put the data starting from fifo->in to buffer end */
l = min ( len , fifo - > size - off ) ;
ret = copy_from_user ( fifo - > buffer + off , from , l ) ;
2010-01-16 04:01:15 +03:00
if ( unlikely ( ret ) ) {
* lenout = ret ;
return - EFAULT ;
}
* lenout = l ;
2009-12-22 01:37:31 +03:00
/* then put the rest (if any) at the beginning of the buffer */
2010-01-16 04:01:15 +03:00
ret = copy_from_user ( fifo - > buffer , from + l , len - l ) ;
* lenout + = ret ? ret : len - l ;
return ret ? - EFAULT : 0 ;
2009-12-22 01:37:32 +03:00
}
2010-01-16 04:01:15 +03:00
static inline int __kfifo_to_user_data ( struct kfifo * fifo ,
void __user * to , unsigned int len , unsigned int off , unsigned * lenout )
2009-12-22 01:37:32 +03:00
{
unsigned int l ;
int ret ;
/*
* Ensure that we sample the fifo - > in index - before - we
* start removing bytes from the kfifo .
*/
smp_rmb ( ) ;
off = __kfifo_off ( fifo , fifo - > out + off ) ;
/* first get the data from fifo->out until the end of the buffer */
l = min ( len , fifo - > size - off ) ;
ret = copy_to_user ( to , fifo - > buffer + off , l ) ;
2010-01-16 04:01:15 +03:00
* lenout = l ;
if ( unlikely ( ret ) ) {
* lenout - = ret ;
return - EFAULT ;
}
2009-12-22 01:37:31 +03:00
2009-12-22 01:37:32 +03:00
/* then get the rest (if any) from the beginning of the buffer */
2010-01-16 04:01:15 +03:00
len - = l ;
ret = copy_to_user ( to + l , fifo - > buffer , len ) ;
if ( unlikely ( ret ) ) {
* lenout + = len - ret ;
return - EFAULT ;
}
* lenout + = len ;
return 0 ;
2009-12-22 01:37:32 +03:00
}
2005-04-17 02:20:36 +04:00
2009-12-22 01:37:32 +03:00
unsigned int __kfifo_in_n ( struct kfifo * fifo ,
const void * from , unsigned int len , unsigned int recsize )
{
if ( kfifo_avail ( fifo ) < len + recsize )
return len + 1 ;
__kfifo_in_data ( fifo , from , len , recsize ) ;
return 0 ;
}
EXPORT_SYMBOL ( __kfifo_in_n ) ;
/**
* kfifo_in - puts some data into the FIFO
* @ fifo : the fifo to be used .
* @ from : the data to be added .
* @ len : the length of the data to be added .
*
* This function copies at most @ len bytes from the @ from buffer into
* the FIFO depending on the free space , and returns the number of
* bytes copied .
*
* Note that with only one concurrent reader and one concurrent
* writer , you don ' t need extra locking to use these functions .
*/
2010-01-16 04:01:12 +03:00
unsigned int kfifo_in ( struct kfifo * fifo , const void * from ,
2009-12-22 01:37:32 +03:00
unsigned int len )
{
len = min ( kfifo_avail ( fifo ) , len ) ;
__kfifo_in_data ( fifo , from , len , 0 ) ;
__kfifo_add_in ( fifo , len ) ;
2005-04-17 02:20:36 +04:00
return len ;
}
2009-12-22 01:37:32 +03:00
EXPORT_SYMBOL ( kfifo_in ) ;
unsigned int __kfifo_in_generic ( struct kfifo * fifo ,
const void * from , unsigned int len , unsigned int recsize )
{
return __kfifo_in_rec ( fifo , from , len , recsize ) ;
}
EXPORT_SYMBOL ( __kfifo_in_generic ) ;
unsigned int __kfifo_out_n ( struct kfifo * fifo ,
void * to , unsigned int len , unsigned int recsize )
{
if ( kfifo_len ( fifo ) < len + recsize )
return len ;
__kfifo_out_data ( fifo , to , len , recsize ) ;
__kfifo_add_out ( fifo , len + recsize ) ;
return 0 ;
}
EXPORT_SYMBOL ( __kfifo_out_n ) ;
2009-12-22 01:37:31 +03:00
/**
2009-12-22 01:37:32 +03:00
* kfifo_out - gets some data from the FIFO
2009-12-22 01:37:31 +03:00
* @ fifo : the fifo to be used .
* @ to : where the data must be copied .
* @ len : the size of the destination buffer .
*
* This function copies at most @ len bytes from the FIFO into the
* @ to buffer and returns the number of copied bytes .
*
* Note that with only one concurrent reader and one concurrent
* writer , you don ' t need extra locking to use these functions .
*/
2010-01-16 04:01:12 +03:00
unsigned int kfifo_out ( struct kfifo * fifo , void * to , unsigned int len )
2009-12-22 01:37:31 +03:00
{
2009-12-22 01:37:32 +03:00
len = min ( kfifo_len ( fifo ) , len ) ;
2009-12-22 01:37:31 +03:00
2009-12-22 01:37:32 +03:00
__kfifo_out_data ( fifo , to , len , 0 ) ;
__kfifo_add_out ( fifo , len ) ;
2009-12-22 01:37:31 +03:00
2009-12-22 01:37:32 +03:00
return len ;
}
EXPORT_SYMBOL ( kfifo_out ) ;
2009-12-22 01:37:31 +03:00
2009-12-22 01:37:32 +03:00
unsigned int __kfifo_out_generic ( struct kfifo * fifo ,
void * to , unsigned int len , unsigned int recsize ,
unsigned int * total )
{
return __kfifo_out_rec ( fifo , to , len , recsize , total ) ;
}
EXPORT_SYMBOL ( __kfifo_out_generic ) ;
2009-12-22 01:37:31 +03:00
2009-12-22 01:37:32 +03:00
unsigned int __kfifo_from_user_n ( struct kfifo * fifo ,
const void __user * from , unsigned int len , unsigned int recsize )
{
2010-01-16 04:01:15 +03:00
unsigned total ;
2009-12-22 01:37:32 +03:00
if ( kfifo_avail ( fifo ) < len + recsize )
return len + 1 ;
2009-12-22 01:37:31 +03:00
2010-01-16 04:01:15 +03:00
__kfifo_from_user_data ( fifo , from , len , recsize , & total ) ;
return total ;
2009-12-22 01:37:32 +03:00
}
EXPORT_SYMBOL ( __kfifo_from_user_n ) ;
2009-12-22 01:37:31 +03:00
2009-12-22 01:37:32 +03:00
/**
* kfifo_from_user - puts some data from user space into the FIFO
* @ fifo : the fifo to be used .
* @ from : pointer to the data to be added .
* @ len : the length of the data to be added .
*
* This function copies at most @ len bytes from the @ from into the
2010-01-16 04:01:15 +03:00
* FIFO depending and returns - EFAULT / 0.
2009-12-22 01:37:32 +03:00
*
* Note that with only one concurrent reader and one concurrent
* writer , you don ' t need extra locking to use these functions .
*/
2010-01-16 04:01:15 +03:00
int kfifo_from_user ( struct kfifo * fifo ,
const void __user * from , unsigned int len , unsigned * total )
2009-12-22 01:37:32 +03:00
{
2010-01-16 04:01:15 +03:00
int ret ;
2009-12-22 01:37:32 +03:00
len = min ( kfifo_avail ( fifo ) , len ) ;
2010-01-16 04:01:15 +03:00
ret = __kfifo_from_user_data ( fifo , from , len , 0 , total ) ;
if ( ret )
return ret ;
2009-12-22 01:37:32 +03:00
__kfifo_add_in ( fifo , len ) ;
2010-01-16 04:01:15 +03:00
return 0 ;
2009-12-22 01:37:32 +03:00
}
EXPORT_SYMBOL ( kfifo_from_user ) ;
2009-12-22 01:37:31 +03:00
2009-12-22 01:37:32 +03:00
unsigned int __kfifo_from_user_generic ( struct kfifo * fifo ,
const void __user * from , unsigned int len , unsigned int recsize )
{
return __kfifo_from_user_rec ( fifo , from , len , recsize ) ;
}
EXPORT_SYMBOL ( __kfifo_from_user_generic ) ;
2009-12-22 01:37:31 +03:00
2009-12-22 01:37:32 +03:00
unsigned int __kfifo_to_user_n ( struct kfifo * fifo ,
void __user * to , unsigned int len , unsigned int reclen ,
unsigned int recsize )
{
2010-01-16 04:01:15 +03:00
unsigned int ret , total ;
2009-12-22 01:37:31 +03:00
2009-12-22 01:37:32 +03:00
if ( kfifo_len ( fifo ) < reclen + recsize )
return len ;
2009-12-22 01:37:31 +03:00
2010-01-16 04:01:15 +03:00
ret = __kfifo_to_user_data ( fifo , to , reclen , recsize , & total ) ;
2009-12-22 01:37:32 +03:00
if ( likely ( ret = = 0 ) )
__kfifo_add_out ( fifo , reclen + recsize ) ;
2010-01-16 04:01:15 +03:00
return total ;
2009-12-22 01:37:32 +03:00
}
EXPORT_SYMBOL ( __kfifo_to_user_n ) ;
/**
* kfifo_to_user - gets data from the FIFO and write it to user space
* @ fifo : the fifo to be used .
* @ to : where the data must be copied .
* @ len : the size of the destination buffer .
2010-01-16 04:01:15 +03:00
@ @ lenout : pointer to output variable with copied data
2009-12-22 01:37:32 +03:00
*
* This function copies at most @ len bytes from the FIFO into the
2010-01-16 04:01:15 +03:00
* @ to buffer and 0 or - EFAULT .
2009-12-22 01:37:32 +03:00
*
* Note that with only one concurrent reader and one concurrent
* writer , you don ' t need extra locking to use these functions .
*/
2010-01-16 04:01:15 +03:00
int kfifo_to_user ( struct kfifo * fifo ,
void __user * to , unsigned int len , unsigned * lenout )
2009-12-22 01:37:32 +03:00
{
2010-01-16 04:01:15 +03:00
int ret ;
2009-12-22 01:37:32 +03:00
len = min ( kfifo_len ( fifo ) , len ) ;
2010-01-16 04:01:15 +03:00
ret = __kfifo_to_user_data ( fifo , to , len , 0 , lenout ) ;
__kfifo_add_out ( fifo , * lenout ) ;
return ret ;
2009-12-22 01:37:31 +03:00
}
EXPORT_SYMBOL ( kfifo_to_user ) ;
2009-12-22 01:37:32 +03:00
unsigned int __kfifo_to_user_generic ( struct kfifo * fifo ,
void __user * to , unsigned int len , unsigned int recsize ,
unsigned int * total )
{
return __kfifo_to_user_rec ( fifo , to , len , recsize , total ) ;
}
EXPORT_SYMBOL ( __kfifo_to_user_generic ) ;
unsigned int __kfifo_peek_generic ( struct kfifo * fifo , unsigned int recsize )
{
if ( recsize = = 0 )
return kfifo_avail ( fifo ) ;
return __kfifo_peek_n ( fifo , recsize ) ;
}
EXPORT_SYMBOL ( __kfifo_peek_generic ) ;
void __kfifo_skip_generic ( struct kfifo * fifo , unsigned int recsize )
{
__kfifo_skip_rec ( fifo , recsize ) ;
}
EXPORT_SYMBOL ( __kfifo_skip_generic ) ;