diff options
author | Stefani Seibold <stefani@seibold.net> | 2009-12-21 17:37:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-22 17:17:55 -0500 |
commit | 45465487897a1c6d508b14b904dc5777f7ec7e04 (patch) | |
tree | 935c8dae68dc793ff2f795d57cf027531475cd53 /drivers/usb/host/fhci-sched.c | |
parent | 2ec91eec47f713e3d158ba5b28a24a85a2cf3650 (diff) |
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>
Diffstat (limited to 'drivers/usb/host/fhci-sched.c')
-rw-r--r-- | drivers/usb/host/fhci-sched.c | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/drivers/usb/host/fhci-sched.c b/drivers/usb/host/fhci-sched.c index 00a29855d0c4..ff43747a614f 100644 --- a/drivers/usb/host/fhci-sched.c +++ b/drivers/usb/host/fhci-sched.c | |||
@@ -37,7 +37,7 @@ static void recycle_frame(struct fhci_usb *usb, struct packet *pkt) | |||
37 | pkt->info = 0; | 37 | pkt->info = 0; |
38 | pkt->priv_data = NULL; | 38 | pkt->priv_data = NULL; |
39 | 39 | ||
40 | cq_put(usb->ep0->empty_frame_Q, pkt); | 40 | cq_put(&usb->ep0->empty_frame_Q, pkt); |
41 | } | 41 | } |
42 | 42 | ||
43 | /* confirm submitted packet */ | 43 | /* confirm submitted packet */ |
@@ -57,7 +57,7 @@ void fhci_transaction_confirm(struct fhci_usb *usb, struct packet *pkt) | |||
57 | if ((td->data + td->actual_len) && trans_len) | 57 | if ((td->data + td->actual_len) && trans_len) |
58 | memcpy(td->data + td->actual_len, pkt->data, | 58 | memcpy(td->data + td->actual_len, pkt->data, |
59 | trans_len); | 59 | trans_len); |
60 | cq_put(usb->ep0->dummy_packets_Q, pkt->data); | 60 | cq_put(&usb->ep0->dummy_packets_Q, pkt->data); |
61 | } | 61 | } |
62 | 62 | ||
63 | recycle_frame(usb, pkt); | 63 | recycle_frame(usb, pkt); |
@@ -213,7 +213,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td) | |||
213 | } | 213 | } |
214 | 214 | ||
215 | /* update frame object fields before transmitting */ | 215 | /* update frame object fields before transmitting */ |
216 | pkt = cq_get(usb->ep0->empty_frame_Q); | 216 | pkt = cq_get(&usb->ep0->empty_frame_Q); |
217 | if (!pkt) { | 217 | if (!pkt) { |
218 | fhci_dbg(usb->fhci, "there is no empty frame\n"); | 218 | fhci_dbg(usb->fhci, "there is no empty frame\n"); |
219 | return -1; | 219 | return -1; |
@@ -222,7 +222,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td) | |||
222 | 222 | ||
223 | pkt->info = 0; | 223 | pkt->info = 0; |
224 | if (data == NULL) { | 224 | if (data == NULL) { |
225 | data = cq_get(usb->ep0->dummy_packets_Q); | 225 | data = cq_get(&usb->ep0->dummy_packets_Q); |
226 | BUG_ON(!data); | 226 | BUG_ON(!data); |
227 | pkt->info = PKT_DUMMY_PACKET; | 227 | pkt->info = PKT_DUMMY_PACKET; |
228 | } | 228 | } |
@@ -246,7 +246,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td) | |||
246 | list_del_init(&td->frame_lh); | 246 | list_del_init(&td->frame_lh); |
247 | td->status = USB_TD_OK; | 247 | td->status = USB_TD_OK; |
248 | if (pkt->info & PKT_DUMMY_PACKET) | 248 | if (pkt->info & PKT_DUMMY_PACKET) |
249 | cq_put(usb->ep0->dummy_packets_Q, pkt->data); | 249 | cq_put(&usb->ep0->dummy_packets_Q, pkt->data); |
250 | recycle_frame(usb, pkt); | 250 | recycle_frame(usb, pkt); |
251 | usb->actual_frame->total_bytes -= (len + PROTOCOL_OVERHEAD); | 251 | usb->actual_frame->total_bytes -= (len + PROTOCOL_OVERHEAD); |
252 | fhci_err(usb->fhci, "host transaction failed\n"); | 252 | fhci_err(usb->fhci, "host transaction failed\n"); |