2009-01-10 05:03:21 +03:00
/*
* Freescale QUICC Engine USB Host Controller Driver
*
* Copyright ( c ) Freescale Semicondutor , Inc . 2006.
* Shlomi Gridish < gridish @ freescale . com >
* Jerry Huang < Chang - Ming . Huang @ freescale . com >
* Copyright ( c ) Logic Product Development , Inc . 2007
* Peter Barada < peterb @ logicpd . com >
* Copyright ( c ) MontaVista Software , Inc . 2008.
* Anton Vorontsov < avorontsov @ ru . mvista . 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 ; either version 2 of the License , or ( at your
* option ) any later version .
*/
# include <linux/kernel.h>
# include <linux/types.h>
# include <linux/errno.h>
# include <linux/list.h>
# include <linux/io.h>
# include <linux/usb.h>
# include "../core/hcd.h"
# include "fhci.h"
# define DUMMY_BD_BUFFER 0xdeadbeef
# define DUMMY2_BD_BUFFER 0xbaadf00d
/* Transaction Descriptors bits */
# define TD_R 0x8000 /* ready bit */
# define TD_W 0x2000 /* wrap bit */
# define TD_I 0x1000 /* interrupt on completion */
# define TD_L 0x0800 /* last */
# define TD_TC 0x0400 /* transmit CRC */
# define TD_CNF 0x0200 /* CNF - Must be always 1 */
# define TD_LSP 0x0100 /* Low-speed transaction */
# define TD_PID 0x00c0 /* packet id */
# define TD_RXER 0x0020 /* Rx error or not */
# define TD_NAK 0x0010 /* No ack. */
# define TD_STAL 0x0008 /* Stall recieved */
# define TD_TO 0x0004 /* time out */
# define TD_UN 0x0002 /* underrun */
# define TD_NO 0x0010 /* Rx Non Octet Aligned Packet */
# define TD_AB 0x0008 /* Frame Aborted */
# define TD_CR 0x0004 /* CRC Error */
# define TD_OV 0x0002 /* Overrun */
# define TD_BOV 0x0001 /* Buffer Overrun */
# define TD_ERRORS (TD_NAK | TD_STAL | TD_TO | TD_UN | \
TD_NO | TD_AB | TD_CR | TD_OV | TD_BOV )
# define TD_PID_DATA0 0x0080 /* Data 0 toggle */
# define TD_PID_DATA1 0x00c0 /* Data 1 toggle */
# define TD_PID_TOGGLE 0x00c0 /* Data 0/1 toggle mask */
# define TD_TOK_SETUP 0x0000
# define TD_TOK_OUT 0x4000
# define TD_TOK_IN 0x8000
# define TD_ISO 0x1000
# define TD_ENDP 0x0780
# define TD_ADDR 0x007f
# define TD_ENDP_SHIFT 7
struct usb_td {
__be16 status ;
__be16 length ;
__be32 buf_ptr ;
__be16 extra ;
__be16 reserved ;
} ;
static struct usb_td __iomem * next_bd ( struct usb_td __iomem * base ,
struct usb_td __iomem * td ,
u16 status )
{
if ( status & TD_W )
return base ;
else
return + + td ;
}
void fhci_push_dummy_bd ( struct endpoint * ep )
{
if ( ep - > already_pushed_dummy_bd = = false ) {
u16 td_status = in_be16 ( & ep - > empty_td - > status ) ;
out_be32 ( & ep - > empty_td - > buf_ptr , DUMMY_BD_BUFFER ) ;
/* get the next TD in the ring */
ep - > empty_td = next_bd ( ep - > td_base , ep - > empty_td , td_status ) ;
ep - > already_pushed_dummy_bd = true ;
}
}
/* destroy an USB endpoint */
void fhci_ep0_free ( struct fhci_usb * usb )
{
struct endpoint * ep ;
int size ;
ep = usb - > ep0 ;
if ( ep ) {
if ( ep - > td_base )
cpm_muram_free ( cpm_muram_offset ( ep - > td_base ) ) ;
2010-01-27 17:09:36 +03:00
if ( kfifo_initialized ( & ep - > conf_frame_Q ) ) {
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-21 14:37:26 -08:00
size = cq_howmany ( & ep - > conf_frame_Q ) ;
2009-01-10 05:03:21 +03:00
for ( ; size ; 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-21 14:37:26 -08:00
struct packet * pkt = cq_get ( & ep - > conf_frame_Q ) ;
2009-01-10 05:03:21 +03:00
kfree ( pkt ) ;
}
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-21 14:37:26 -08:00
cq_delete ( & ep - > conf_frame_Q ) ;
2009-01-10 05:03:21 +03:00
}
2010-01-27 17:09:36 +03:00
if ( kfifo_initialized ( & ep - > empty_frame_Q ) ) {
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-21 14:37:26 -08:00
size = cq_howmany ( & ep - > empty_frame_Q ) ;
2009-01-10 05:03:21 +03:00
for ( ; size ; 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-21 14:37:26 -08:00
struct packet * pkt = cq_get ( & ep - > empty_frame_Q ) ;
2009-01-10 05:03:21 +03:00
kfree ( pkt ) ;
}
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-21 14:37:26 -08:00
cq_delete ( & ep - > empty_frame_Q ) ;
2009-01-10 05:03:21 +03:00
}
2010-01-27 17:09:36 +03:00
if ( kfifo_initialized ( & ep - > dummy_packets_Q ) ) {
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-21 14:37:26 -08:00
size = cq_howmany ( & ep - > dummy_packets_Q ) ;
2009-01-10 05:03:21 +03:00
for ( ; size ; 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-21 14:37:26 -08:00
u8 * buff = cq_get ( & ep - > dummy_packets_Q ) ;
2009-01-10 05:03:21 +03:00
kfree ( buff ) ;
}
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-21 14:37:26 -08:00
cq_delete ( & ep - > dummy_packets_Q ) ;
2009-01-10 05:03:21 +03:00
}
kfree ( ep ) ;
usb - > ep0 = NULL ;
}
}
/*
* create the endpoint structure
*
* arguments :
* usb A pointer to the data structure of the USB
* data_mem The data memory partition ( BUS )
* ring_len TD ring length
*/
u32 fhci_create_ep ( struct fhci_usb * usb , enum fhci_mem_alloc data_mem ,
u32 ring_len )
{
struct endpoint * ep ;
struct usb_td __iomem * td ;
unsigned long ep_offset ;
char * err_for = " enpoint PRAM " ;
int ep_mem_size ;
u32 i ;
/* we need at least 3 TDs in the ring */
if ( ! ( ring_len > 2 ) ) {
fhci_err ( usb - > fhci , " illegal TD ring length parameters \n " ) ;
return - EINVAL ;
}
ep = kzalloc ( sizeof ( * ep ) , GFP_KERNEL ) ;
if ( ! ep )
return - ENOMEM ;
ep_mem_size = ring_len * sizeof ( * td ) + sizeof ( struct fhci_ep_pram ) ;
ep_offset = cpm_muram_alloc ( ep_mem_size , 32 ) ;
if ( IS_ERR_VALUE ( ep_offset ) )
goto err ;
ep - > td_base = cpm_muram_addr ( ep_offset ) ;
/* zero all queue pointers */
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-21 14:37:26 -08:00
if ( cq_new ( & ep - > conf_frame_Q , ring_len + 2 ) | |
cq_new ( & ep - > empty_frame_Q , ring_len + 2 ) | |
cq_new ( & ep - > dummy_packets_Q , ring_len + 2 ) ) {
2009-01-10 05:03:21 +03:00
err_for = " frame_queues " ;
goto err ;
}
for ( i = 0 ; i < ( ring_len + 1 ) ; i + + ) {
struct packet * pkt ;
u8 * buff ;
pkt = kmalloc ( sizeof ( * pkt ) , GFP_KERNEL ) ;
if ( ! pkt ) {
err_for = " frame " ;
goto err ;
}
buff = kmalloc ( 1028 * sizeof ( * buff ) , GFP_KERNEL ) ;
if ( ! buff ) {
kfree ( pkt ) ;
err_for = " buffer " ;
goto err ;
}
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-21 14:37:26 -08:00
cq_put ( & ep - > empty_frame_Q , pkt ) ;
cq_put ( & ep - > dummy_packets_Q , buff ) ;
2009-01-10 05:03:21 +03:00
}
/* we put the endpoint parameter RAM right behind the TD ring */
ep - > ep_pram_ptr = ( void __iomem * ) ep - > td_base + sizeof ( * td ) * ring_len ;
ep - > conf_td = ep - > td_base ;
ep - > empty_td = ep - > td_base ;
ep - > already_pushed_dummy_bd = false ;
/* initialize tds */
td = ep - > td_base ;
for ( i = 0 ; i < ring_len ; i + + ) {
out_be32 ( & td - > buf_ptr , 0 ) ;
out_be16 ( & td - > status , 0 ) ;
out_be16 ( & td - > length , 0 ) ;
out_be16 ( & td - > extra , 0 ) ;
td + + ;
}
td - - ;
out_be16 ( & td - > status , TD_W ) ; /* for last TD set Wrap bit */
out_be16 ( & td - > length , 0 ) ;
/* endpoint structure has been created */
usb - > ep0 = ep ;
return 0 ;
err :
fhci_ep0_free ( usb ) ;
kfree ( ep ) ;
fhci_err ( usb - > fhci , " no memory for the %s \n " , err_for ) ;
return - ENOMEM ;
}
/*
* initialize the endpoint register according to the given parameters
*
* artuments :
* usb A pointer to the data strucutre of the USB
* ep A pointer to the endpoint structre
* data_mem The data memory partition ( BUS )
*/
void fhci_init_ep_registers ( struct fhci_usb * usb , struct endpoint * ep ,
enum fhci_mem_alloc data_mem )
{
u8 rt ;
/* set the endpoint registers according to the endpoint */
out_be16 ( & usb - > fhci - > regs - > usb_ep [ 0 ] ,
USB_TRANS_CTR | USB_EP_MF | USB_EP_RTE ) ;
out_be16 ( & usb - > fhci - > pram - > ep_ptr [ 0 ] ,
cpm_muram_offset ( ep - > ep_pram_ptr ) ) ;
rt = ( BUS_MODE_BO_BE | BUS_MODE_GBL ) ;
# ifdef MULTI_DATA_BUS
if ( data_mem = = MEM_SECONDARY )
rt | = BUS_MODE_DTB ;
# endif
out_8 ( & ep - > ep_pram_ptr - > rx_func_code , rt ) ;
out_8 ( & ep - > ep_pram_ptr - > tx_func_code , rt ) ;
out_be16 ( & ep - > ep_pram_ptr - > rx_buff_len , 1028 ) ;
out_be16 ( & ep - > ep_pram_ptr - > rx_base , 0 ) ;
out_be16 ( & ep - > ep_pram_ptr - > tx_base , cpm_muram_offset ( ep - > td_base ) ) ;
out_be16 ( & ep - > ep_pram_ptr - > rx_bd_ptr , 0 ) ;
out_be16 ( & ep - > ep_pram_ptr - > tx_bd_ptr , cpm_muram_offset ( ep - > td_base ) ) ;
out_be32 ( & ep - > ep_pram_ptr - > tx_state , 0 ) ;
}
/*
* Collect the submitted frames and inform the application about them
* It is also prepearing the TDs for new frames . If the Tx interrupts
* are diabled , the application should call that routine to get
* confirmation about the submitted frames . Otherwise , the routine is
* called frome the interrupt service routine during the Tx interrupt .
* In that case the application is informed by calling the application
* specific ' fhci_transaction_confirm ' routine
*/
static void fhci_td_transaction_confirm ( struct fhci_usb * usb )
{
struct endpoint * ep = usb - > ep0 ;
struct packet * pkt ;
struct usb_td __iomem * td ;
u16 extra_data ;
u16 td_status ;
u16 td_length ;
u32 buf ;
/*
* collect transmitted BDs from the chip . The routine clears all BDs
* with R bit = 0 and the pointer to data buffer is not NULL , that is
* BDs which point to the transmitted data buffer
*/
while ( 1 ) {
td = ep - > conf_td ;
td_status = in_be16 ( & td - > status ) ;
td_length = in_be16 ( & td - > length ) ;
buf = in_be32 ( & td - > buf_ptr ) ;
extra_data = in_be16 ( & td - > extra ) ;
/* check if the TD is empty */
if ( ! ( ! ( td_status & TD_R ) & & ( ( td_status & ~ TD_W ) | | buf ) ) )
break ;
/* check if it is a dummy buffer */
else if ( ( buf = = DUMMY_BD_BUFFER ) & & ! ( td_status & ~ TD_W ) )
break ;
/* mark TD as empty */
clrbits16 ( & td - > status , ~ TD_W ) ;
out_be16 ( & td - > length , 0 ) ;
out_be32 ( & td - > buf_ptr , 0 ) ;
out_be16 ( & td - > extra , 0 ) ;
/* advance the TD pointer */
ep - > conf_td = next_bd ( ep - > td_base , ep - > conf_td , td_status ) ;
/* check if it is a dummy buffer(type2) */
if ( ( buf = = DUMMY2_BD_BUFFER ) & & ! ( td_status & ~ TD_W ) )
continue ;
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-21 14:37:26 -08:00
pkt = cq_get ( & ep - > conf_frame_Q ) ;
2009-01-10 05:03:21 +03:00
if ( ! pkt )
fhci_err ( usb - > fhci , " no frame to confirm \n " ) ;
if ( td_status & TD_ERRORS ) {
if ( td_status & TD_RXER ) {
if ( td_status & TD_CR )
pkt - > status = USB_TD_RX_ER_CRC ;
else if ( td_status & TD_AB )
pkt - > status = USB_TD_RX_ER_BITSTUFF ;
else if ( td_status & TD_OV )
pkt - > status = USB_TD_RX_ER_OVERUN ;
else if ( td_status & TD_BOV )
pkt - > status = USB_TD_RX_DATA_OVERUN ;
else if ( td_status & TD_NO )
pkt - > status = USB_TD_RX_ER_NONOCT ;
else
fhci_err ( usb - > fhci , " illegal error "
" occured \n " ) ;
} else if ( td_status & TD_NAK )
pkt - > status = USB_TD_TX_ER_NAK ;
else if ( td_status & TD_TO )
pkt - > status = USB_TD_TX_ER_TIMEOUT ;
else if ( td_status & TD_UN )
pkt - > status = USB_TD_TX_ER_UNDERUN ;
else if ( td_status & TD_STAL )
pkt - > status = USB_TD_TX_ER_STALL ;
else
fhci_err ( usb - > fhci , " illegal error occured \n " ) ;
} else if ( ( extra_data & TD_TOK_IN ) & &
pkt - > len > td_length - CRC_SIZE ) {
pkt - > status = USB_TD_RX_DATA_UNDERUN ;
}
if ( extra_data & TD_TOK_IN )
pkt - > len = td_length - CRC_SIZE ;
else if ( pkt - > info & PKT_ZLP )
pkt - > len = 0 ;
else
pkt - > len = td_length ;
fhci_transaction_confirm ( usb , pkt ) ;
}
}
/*
* Submitting a data frame to a specified endpoint of a USB device
* The frame is put in the driver ' s transmit queue for this endpoint
*
* Arguments :
* usb A pointer to the USB structure
* pkt A pointer to the user frame structure
* trans_type Transaction tyep - IN , OUT or SETUP
* dest_addr Device address - 0 ~ 127
* dest_ep Endpoint number of the device - 0 ~ 16
* trans_mode Pipe type - ISO , Interrupt , bulk or control
* dest_speed USB speed - Low speed or FULL speed
* data_toggle Data sequence toggle - 0 or 1
*/
u32 fhci_host_transaction ( struct fhci_usb * usb ,
struct packet * pkt ,
enum fhci_ta_type trans_type ,
u8 dest_addr ,
u8 dest_ep ,
enum fhci_tf_mode trans_mode ,
enum fhci_speed dest_speed , u8 data_toggle )
{
struct endpoint * ep = usb - > ep0 ;
struct usb_td __iomem * td ;
u16 extra_data ;
u16 td_status ;
fhci_usb_disable_interrupt ( usb ) ;
/* start from the next BD that should be filled */
td = ep - > empty_td ;
td_status = in_be16 ( & td - > status ) ;
if ( td_status & TD_R & & in_be16 ( & td - > length ) ) {
/* if the TD is not free */
fhci_usb_enable_interrupt ( usb ) ;
return - 1 ;
}
/* get the next TD in the ring */
ep - > empty_td = next_bd ( ep - > td_base , ep - > empty_td , td_status ) ;
fhci_usb_enable_interrupt ( usb ) ;
pkt - > priv_data = td ;
out_be32 ( & td - > buf_ptr , virt_to_phys ( pkt - > data ) ) ;
/* sets up transaction parameters - addr,endp,dir,and type */
extra_data = ( dest_ep < < TD_ENDP_SHIFT ) | dest_addr ;
switch ( trans_type ) {
case FHCI_TA_IN :
extra_data | = TD_TOK_IN ;
break ;
case FHCI_TA_OUT :
extra_data | = TD_TOK_OUT ;
break ;
case FHCI_TA_SETUP :
extra_data | = TD_TOK_SETUP ;
break ;
}
if ( trans_mode = = FHCI_TF_ISO )
extra_data | = TD_ISO ;
out_be16 ( & td - > extra , extra_data ) ;
/* sets up the buffer descriptor */
td_status = ( ( td_status & TD_W ) | TD_R | TD_L | TD_I | TD_CNF ) ;
if ( ! ( pkt - > info & PKT_NO_CRC ) )
td_status | = TD_TC ;
switch ( trans_type ) {
case FHCI_TA_IN :
if ( data_toggle )
pkt - > info | = PKT_PID_DATA1 ;
else
pkt - > info | = PKT_PID_DATA0 ;
break ;
default :
if ( data_toggle ) {
td_status | = TD_PID_DATA1 ;
pkt - > info | = PKT_PID_DATA1 ;
} else {
td_status | = TD_PID_DATA0 ;
pkt - > info | = PKT_PID_DATA0 ;
}
break ;
}
if ( ( dest_speed = = FHCI_LOW_SPEED ) & &
( usb - > port_status = = FHCI_PORT_FULL ) )
td_status | = TD_LSP ;
out_be16 ( & td - > status , td_status ) ;
/* set up buffer length */
if ( trans_type = = FHCI_TA_IN )
out_be16 ( & td - > length , pkt - > len + CRC_SIZE ) ;
else
out_be16 ( & td - > length , pkt - > len ) ;
/* put the frame to the confirmation queue */
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-21 14:37:26 -08:00
cq_put ( & ep - > conf_frame_Q , pkt ) ;
2009-01-10 05:03:21 +03: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-21 14:37:26 -08:00
if ( cq_howmany ( & ep - > conf_frame_Q ) = = 1 )
2009-01-10 05:03:21 +03:00
out_8 ( & usb - > fhci - > regs - > usb_comm , USB_CMD_STR_FIFO ) ;
return 0 ;
}
/* Reset the Tx BD ring */
void fhci_flush_bds ( struct fhci_usb * usb )
{
u16 extra_data ;
u16 td_status ;
u32 buf ;
struct usb_td __iomem * td ;
struct endpoint * ep = usb - > ep0 ;
td = ep - > td_base ;
while ( 1 ) {
td_status = in_be16 ( & td - > status ) ;
buf = in_be32 ( & td - > buf_ptr ) ;
extra_data = in_be16 ( & td - > extra ) ;
/* if the TD is not empty - we'll confirm it as Timeout */
if ( td_status & TD_R )
out_be16 ( & td - > status , ( td_status & ~ TD_R ) | TD_TO ) ;
/* if this TD is dummy - let's skip this TD */
else if ( in_be32 ( & td - > buf_ptr ) = = DUMMY_BD_BUFFER )
out_be32 ( & td - > buf_ptr , DUMMY2_BD_BUFFER ) ;
/* if this is the last TD - break */
if ( td_status & TD_W )
break ;
td + + ;
}
fhci_td_transaction_confirm ( usb ) ;
td = ep - > td_base ;
do {
out_be16 ( & td - > status , 0 ) ;
out_be16 ( & td - > length , 0 ) ;
out_be32 ( & td - > buf_ptr , 0 ) ;
out_be16 ( & td - > extra , 0 ) ;
td + + ;
} while ( ! ( in_be16 ( & td - > status ) & TD_W ) ) ;
out_be16 ( & td - > status , TD_W ) ; /* for last TD set Wrap bit */
out_be16 ( & td - > length , 0 ) ;
out_be32 ( & td - > buf_ptr , 0 ) ;
out_be16 ( & td - > extra , 0 ) ;
out_be16 ( & ep - > ep_pram_ptr - > tx_bd_ptr ,
in_be16 ( & ep - > ep_pram_ptr - > tx_base ) ) ;
out_be32 ( & ep - > ep_pram_ptr - > tx_state , 0 ) ;
out_be16 ( & ep - > ep_pram_ptr - > tx_cnt , 0 ) ;
ep - > empty_td = ep - > td_base ;
ep - > conf_td = ep - > td_base ;
}
/*
* Flush all transmitted packets from TDs in the actual frame .
* This routine is called when something wrong with the controller and
* we want to get rid of the actual frame and start again next frame
*/
void fhci_flush_actual_frame ( struct fhci_usb * usb )
{
u8 mode ;
u16 tb_ptr ;
u16 extra_data ;
u16 td_status ;
u32 buf_ptr ;
struct usb_td __iomem * td ;
struct endpoint * ep = usb - > ep0 ;
/* disable the USB controller */
mode = in_8 ( & usb - > fhci - > regs - > usb_mod ) ;
out_8 ( & usb - > fhci - > regs - > usb_mod , mode & ~ USB_MODE_EN ) ;
tb_ptr = in_be16 ( & ep - > ep_pram_ptr - > tx_bd_ptr ) ;
td = cpm_muram_addr ( tb_ptr ) ;
td_status = in_be16 ( & td - > status ) ;
buf_ptr = in_be32 ( & td - > buf_ptr ) ;
extra_data = in_be16 ( & td - > extra ) ;
do {
if ( td_status & TD_R ) {
out_be16 ( & td - > status , ( td_status & ~ TD_R ) | TD_TO ) ;
} else {
out_be32 ( & td - > buf_ptr , 0 ) ;
ep - > already_pushed_dummy_bd = false ;
break ;
}
/* advance the TD pointer */
td = next_bd ( ep - > td_base , td , td_status ) ;
td_status = in_be16 ( & td - > status ) ;
buf_ptr = in_be32 ( & td - > buf_ptr ) ;
extra_data = in_be16 ( & td - > extra ) ;
} while ( ( td_status & TD_R ) | | buf_ptr ) ;
fhci_td_transaction_confirm ( usb ) ;
out_be16 ( & ep - > ep_pram_ptr - > tx_bd_ptr ,
in_be16 ( & ep - > ep_pram_ptr - > tx_base ) ) ;
out_be32 ( & ep - > ep_pram_ptr - > tx_state , 0 ) ;
out_be16 ( & ep - > ep_pram_ptr - > tx_cnt , 0 ) ;
ep - > empty_td = ep - > td_base ;
ep - > conf_td = ep - > td_base ;
usb - > actual_frame - > frame_status = FRAME_TIMER_END_TRANSMISSION ;
/* reset the event register */
out_be16 ( & usb - > fhci - > regs - > usb_event , 0xffff ) ;
/* enable the USB controller */
out_8 ( & usb - > fhci - > regs - > usb_mod , mode | USB_MODE_EN ) ;
}
/* handles Tx confirm and Tx error interrupt */
void fhci_tx_conf_interrupt ( struct fhci_usb * usb )
{
fhci_td_transaction_confirm ( usb ) ;
/*
* Schedule another transaction to this frame only if we have
* already confirmed all transaction in the frame .
*/
if ( ( ( fhci_get_sof_timer_count ( usb ) < usb - > max_frame_usage ) | |
( usb - > actual_frame - > frame_status & FRAME_END_TRANSMISSION ) ) & &
( list_empty ( & usb - > actual_frame - > tds_list ) ) )
fhci_schedule_transactions ( usb ) ;
}
void fhci_host_transmit_actual_frame ( struct fhci_usb * usb )
{
u16 tb_ptr ;
u16 td_status ;
struct usb_td __iomem * td ;
struct endpoint * ep = usb - > ep0 ;
tb_ptr = in_be16 ( & ep - > ep_pram_ptr - > tx_bd_ptr ) ;
td = cpm_muram_addr ( tb_ptr ) ;
if ( in_be32 ( & td - > buf_ptr ) = = DUMMY_BD_BUFFER ) {
struct usb_td __iomem * old_td = td ;
ep - > already_pushed_dummy_bd = false ;
td_status = in_be16 ( & td - > status ) ;
/* gets the next TD in the ring */
td = next_bd ( ep - > td_base , td , td_status ) ;
tb_ptr = cpm_muram_offset ( td ) ;
out_be16 ( & ep - > ep_pram_ptr - > tx_bd_ptr , tb_ptr ) ;
/* start transmit only if we have something in the TDs */
if ( in_be16 ( & td - > status ) & TD_R )
out_8 ( & usb - > fhci - > regs - > usb_comm , USB_CMD_STR_FIFO ) ;
if ( in_be32 ( & ep - > conf_td - > buf_ptr ) = = DUMMY_BD_BUFFER ) {
out_be32 ( & old_td - > buf_ptr , 0 ) ;
ep - > conf_td = next_bd ( ep - > td_base , ep - > conf_td ,
td_status ) ;
} else {
out_be32 ( & old_td - > buf_ptr , DUMMY2_BD_BUFFER ) ;
}
}
}