mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -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.
[[email protected]: fix warning]
Signed-off-by: Stefani Seibold <[email protected]>
Acked-by: Greg Kroah-Hartman <[email protected]>
Acked-by: Mauro Carvalho Chehab <[email protected]>
Acked-by: Andi Kleen <[email protected]>
Acked-by: Arnd Bergmann <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
parent
2ec91eec47
commit
4546548789
24 changed files with 238 additions and 259 deletions
|
|
@ -37,7 +37,7 @@ static void recycle_frame(struct fhci_usb *usb, struct packet *pkt)
|
|||
pkt->info = 0;
|
||||
pkt->priv_data = NULL;
|
||||
|
||||
cq_put(usb->ep0->empty_frame_Q, pkt);
|
||||
cq_put(&usb->ep0->empty_frame_Q, pkt);
|
||||
}
|
||||
|
||||
/* confirm submitted packet */
|
||||
|
|
@ -57,7 +57,7 @@ void fhci_transaction_confirm(struct fhci_usb *usb, struct packet *pkt)
|
|||
if ((td->data + td->actual_len) && trans_len)
|
||||
memcpy(td->data + td->actual_len, pkt->data,
|
||||
trans_len);
|
||||
cq_put(usb->ep0->dummy_packets_Q, pkt->data);
|
||||
cq_put(&usb->ep0->dummy_packets_Q, pkt->data);
|
||||
}
|
||||
|
||||
recycle_frame(usb, pkt);
|
||||
|
|
@ -213,7 +213,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td)
|
|||
}
|
||||
|
||||
/* update frame object fields before transmitting */
|
||||
pkt = cq_get(usb->ep0->empty_frame_Q);
|
||||
pkt = cq_get(&usb->ep0->empty_frame_Q);
|
||||
if (!pkt) {
|
||||
fhci_dbg(usb->fhci, "there is no empty frame\n");
|
||||
return -1;
|
||||
|
|
@ -222,7 +222,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td)
|
|||
|
||||
pkt->info = 0;
|
||||
if (data == NULL) {
|
||||
data = cq_get(usb->ep0->dummy_packets_Q);
|
||||
data = cq_get(&usb->ep0->dummy_packets_Q);
|
||||
BUG_ON(!data);
|
||||
pkt->info = PKT_DUMMY_PACKET;
|
||||
}
|
||||
|
|
@ -246,7 +246,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td)
|
|||
list_del_init(&td->frame_lh);
|
||||
td->status = USB_TD_OK;
|
||||
if (pkt->info & PKT_DUMMY_PACKET)
|
||||
cq_put(usb->ep0->dummy_packets_Q, pkt->data);
|
||||
cq_put(&usb->ep0->dummy_packets_Q, pkt->data);
|
||||
recycle_frame(usb, pkt);
|
||||
usb->actual_frame->total_bytes -= (len + PROTOCOL_OVERHEAD);
|
||||
fhci_err(usb->fhci, "host transaction failed\n");
|
||||
|
|
|
|||
|
|
@ -106,33 +106,33 @@ void fhci_ep0_free(struct fhci_usb *usb)
|
|||
cpm_muram_free(cpm_muram_offset(ep->td_base));
|
||||
|
||||
if (ep->conf_frame_Q) {
|
||||
size = cq_howmany(ep->conf_frame_Q);
|
||||
size = cq_howmany(&ep->conf_frame_Q);
|
||||
for (; size; size--) {
|
||||
struct packet *pkt = cq_get(ep->conf_frame_Q);
|
||||
struct packet *pkt = cq_get(&ep->conf_frame_Q);
|
||||
|
||||
kfree(pkt);
|
||||
}
|
||||
cq_delete(ep->conf_frame_Q);
|
||||
cq_delete(&ep->conf_frame_Q);
|
||||
}
|
||||
|
||||
if (ep->empty_frame_Q) {
|
||||
size = cq_howmany(ep->empty_frame_Q);
|
||||
size = cq_howmany(&ep->empty_frame_Q);
|
||||
for (; size; size--) {
|
||||
struct packet *pkt = cq_get(ep->empty_frame_Q);
|
||||
struct packet *pkt = cq_get(&ep->empty_frame_Q);
|
||||
|
||||
kfree(pkt);
|
||||
}
|
||||
cq_delete(ep->empty_frame_Q);
|
||||
cq_delete(&ep->empty_frame_Q);
|
||||
}
|
||||
|
||||
if (ep->dummy_packets_Q) {
|
||||
size = cq_howmany(ep->dummy_packets_Q);
|
||||
size = cq_howmany(&ep->dummy_packets_Q);
|
||||
for (; size; size--) {
|
||||
u8 *buff = cq_get(ep->dummy_packets_Q);
|
||||
u8 *buff = cq_get(&ep->dummy_packets_Q);
|
||||
|
||||
kfree(buff);
|
||||
}
|
||||
cq_delete(ep->dummy_packets_Q);
|
||||
cq_delete(&ep->dummy_packets_Q);
|
||||
}
|
||||
|
||||
kfree(ep);
|
||||
|
|
@ -175,10 +175,9 @@ u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem,
|
|||
ep->td_base = cpm_muram_addr(ep_offset);
|
||||
|
||||
/* zero all queue pointers */
|
||||
ep->conf_frame_Q = cq_new(ring_len + 2);
|
||||
ep->empty_frame_Q = cq_new(ring_len + 2);
|
||||
ep->dummy_packets_Q = cq_new(ring_len + 2);
|
||||
if (!ep->conf_frame_Q || !ep->empty_frame_Q || !ep->dummy_packets_Q) {
|
||||
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)) {
|
||||
err_for = "frame_queues";
|
||||
goto err;
|
||||
}
|
||||
|
|
@ -199,8 +198,8 @@ u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem,
|
|||
err_for = "buffer";
|
||||
goto err;
|
||||
}
|
||||
cq_put(ep->empty_frame_Q, pkt);
|
||||
cq_put(ep->dummy_packets_Q, buff);
|
||||
cq_put(&ep->empty_frame_Q, pkt);
|
||||
cq_put(&ep->dummy_packets_Q, buff);
|
||||
}
|
||||
|
||||
/* we put the endpoint parameter RAM right behind the TD ring */
|
||||
|
|
@ -319,7 +318,7 @@ static void fhci_td_transaction_confirm(struct fhci_usb *usb)
|
|||
if ((buf == DUMMY2_BD_BUFFER) && !(td_status & ~TD_W))
|
||||
continue;
|
||||
|
||||
pkt = cq_get(ep->conf_frame_Q);
|
||||
pkt = cq_get(&ep->conf_frame_Q);
|
||||
if (!pkt)
|
||||
fhci_err(usb->fhci, "no frame to confirm\n");
|
||||
|
||||
|
|
@ -460,9 +459,9 @@ u32 fhci_host_transaction(struct fhci_usb *usb,
|
|||
out_be16(&td->length, pkt->len);
|
||||
|
||||
/* put the frame to the confirmation queue */
|
||||
cq_put(ep->conf_frame_Q, pkt);
|
||||
cq_put(&ep->conf_frame_Q, pkt);
|
||||
|
||||
if (cq_howmany(ep->conf_frame_Q) == 1)
|
||||
if (cq_howmany(&ep->conf_frame_Q) == 1)
|
||||
out_8(&usb->fhci->regs->usb_comm, USB_CMD_STR_FIFO);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -423,9 +423,9 @@ struct endpoint {
|
|||
struct usb_td __iomem *td_base; /* first TD in the ring */
|
||||
struct usb_td __iomem *conf_td; /* next TD for confirm after transac */
|
||||
struct usb_td __iomem *empty_td;/* next TD for new transaction req. */
|
||||
struct kfifo *empty_frame_Q; /* Empty frames list to use */
|
||||
struct kfifo *conf_frame_Q; /* frames passed to TDs,waiting for tx */
|
||||
struct kfifo *dummy_packets_Q;/* dummy packets for the CRC overun */
|
||||
struct kfifo empty_frame_Q; /* Empty frames list to use */
|
||||
struct kfifo conf_frame_Q; /* frames passed to TDs,waiting for tx */
|
||||
struct kfifo dummy_packets_Q;/* dummy packets for the CRC overun */
|
||||
|
||||
bool already_pushed_dummy_bd;
|
||||
};
|
||||
|
|
@ -493,9 +493,9 @@ static inline struct usb_hcd *fhci_to_hcd(struct fhci_hcd *fhci)
|
|||
}
|
||||
|
||||
/* fifo of pointers */
|
||||
static inline struct kfifo *cq_new(int size)
|
||||
static inline int cq_new(struct kfifo *fifo, int size)
|
||||
{
|
||||
return kfifo_alloc(size * sizeof(void *), GFP_KERNEL, NULL);
|
||||
return kfifo_alloc(fifo, size * sizeof(void *), GFP_KERNEL, NULL);
|
||||
}
|
||||
|
||||
static inline void cq_delete(struct kfifo *kfifo)
|
||||
|
|
|
|||
|
|
@ -939,9 +939,8 @@ int usb_serial_probe(struct usb_interface *interface,
|
|||
dev_err(&interface->dev, "No free urbs available\n");
|
||||
goto probe_error;
|
||||
}
|
||||
port->write_fifo = kfifo_alloc(PAGE_SIZE, GFP_KERNEL,
|
||||
&port->lock);
|
||||
if (IS_ERR(port->write_fifo))
|
||||
if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL,
|
||||
&port->lock))
|
||||
goto probe_error;
|
||||
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
|
||||
port->bulk_out_size = buffer_size;
|
||||
|
|
|
|||
Loading…
Reference in a new issue