]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
usb: gadget: u_serial: Use kfifo instead of homemade circular buffer
authorLu Baolu <baolu.lu@linux.intel.com>
Tue, 28 Nov 2017 04:46:28 +0000 (12:46 +0800)
committerFelipe Balbi <felipe.balbi@linux.intel.com>
Mon, 11 Dec 2017 10:36:50 +0000 (12:36 +0200)
The kernel FIFO implementation, kfifo, provides interfaces to manipulate
a first-in-first-out circular buffer.  Use kfifo instead of the homemade
one to make the code more concise and readable.

Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
drivers/usb/gadget/function/u_serial.c

index 4d653d2960d4e2141a4509186b5f1b2ddb8200c9..29436f75bbe06b5e94df5a063a1a5222c3b6509d 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/console.h>
 #include <linux/kthread.h>
+#include <linux/kfifo.h>
 
 #include "u_serial.h"
 
 #define WRITE_BUF_SIZE         8192            /* TX only */
 #define GS_CONSOLE_BUF_SIZE    8192
 
-/* circular buffer */
-struct gs_buf {
-       unsigned                buf_size;
-       char                    *buf_buf;
-       char                    *buf_get;
-       char                    *buf_put;
-};
-
 /* console info */
 struct gscons_info {
        struct gs_port          *port;
        struct task_struct      *console_thread;
-       struct gs_buf           con_buf;
+       struct kfifo            con_buf;
        /* protect the buf and busy flag */
        spinlock_t              con_lock;
        int                     req_busy;
@@ -122,7 +115,7 @@ struct gs_port {
        struct list_head        write_pool;
        int write_started;
        int write_allocated;
-       struct gs_buf           port_write_buf;
+       struct kfifo            port_write_buf;
        wait_queue_head_t       drain_wait;     /* wait while writes drain */
        bool                    write_busy;
        wait_queue_head_t       close_wait;
@@ -154,144 +147,6 @@ static struct portmaster {
 
 /*-------------------------------------------------------------------------*/
 
-/* Circular Buffer */
-
-/*
- * gs_buf_alloc
- *
- * Allocate a circular buffer and all associated memory.
- */
-static int gs_buf_alloc(struct gs_buf *gb, unsigned size)
-{
-       gb->buf_buf = kmalloc(size, GFP_KERNEL);
-       if (gb->buf_buf == NULL)
-               return -ENOMEM;
-
-       gb->buf_size = size;
-       gb->buf_put = gb->buf_buf;
-       gb->buf_get = gb->buf_buf;
-
-       return 0;
-}
-
-/*
- * gs_buf_free
- *
- * Free the buffer and all associated memory.
- */
-static void gs_buf_free(struct gs_buf *gb)
-{
-       kfree(gb->buf_buf);
-       gb->buf_buf = NULL;
-}
-
-/*
- * gs_buf_clear
- *
- * Clear out all data in the circular buffer.
- */
-static void gs_buf_clear(struct gs_buf *gb)
-{
-       gb->buf_get = gb->buf_put;
-       /* equivalent to a get of all data available */
-}
-
-/*
- * gs_buf_data_avail
- *
- * Return the number of bytes of data written into the circular
- * buffer.
- */
-static unsigned gs_buf_data_avail(struct gs_buf *gb)
-{
-       return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size;
-}
-
-/*
- * gs_buf_space_avail
- *
- * Return the number of bytes of space available in the circular
- * buffer.
- */
-static unsigned gs_buf_space_avail(struct gs_buf *gb)
-{
-       return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size;
-}
-
-/*
- * gs_buf_put
- *
- * Copy data data from a user buffer and put it into the circular buffer.
- * Restrict to the amount of space available.
- *
- * Return the number of bytes copied.
- */
-static unsigned
-gs_buf_put(struct gs_buf *gb, const char *buf, unsigned count)
-{
-       unsigned len;
-
-       len  = gs_buf_space_avail(gb);
-       if (count > len)
-               count = len;
-
-       if (count == 0)
-               return 0;
-
-       len = gb->buf_buf + gb->buf_size - gb->buf_put;
-       if (count > len) {
-               memcpy(gb->buf_put, buf, len);
-               memcpy(gb->buf_buf, buf+len, count - len);
-               gb->buf_put = gb->buf_buf + count - len;
-       } else {
-               memcpy(gb->buf_put, buf, count);
-               if (count < len)
-                       gb->buf_put += count;
-               else /* count == len */
-                       gb->buf_put = gb->buf_buf;
-       }
-
-       return count;
-}
-
-/*
- * gs_buf_get
- *
- * Get data from the circular buffer and copy to the given buffer.
- * Restrict to the amount of data available.
- *
- * Return the number of bytes copied.
- */
-static unsigned
-gs_buf_get(struct gs_buf *gb, char *buf, unsigned count)
-{
-       unsigned len;
-
-       len = gs_buf_data_avail(gb);
-       if (count > len)
-               count = len;
-
-       if (count == 0)
-               return 0;
-
-       len = gb->buf_buf + gb->buf_size - gb->buf_get;
-       if (count > len) {
-               memcpy(buf, gb->buf_get, len);
-               memcpy(buf+len, gb->buf_buf, count - len);
-               gb->buf_get = gb->buf_buf + count - len;
-       } else {
-               memcpy(buf, gb->buf_get, count);
-               if (count < len)
-                       gb->buf_get += count;
-               else /* count == len */
-                       gb->buf_get = gb->buf_buf;
-       }
-
-       return count;
-}
-
-/*-------------------------------------------------------------------------*/
-
 /* I/O glue between TTY (upper) and USB function (lower) driver layers */
 
 /*
@@ -346,11 +201,11 @@ gs_send_packet(struct gs_port *port, char *packet, unsigned size)
 {
        unsigned len;
 
-       len = gs_buf_data_avail(&port->port_write_buf);
+       len = kfifo_len(&port->port_write_buf);
        if (len < size)
                size = len;
        if (size != 0)
-               size = gs_buf_get(&port->port_write_buf, packet, size);
+               size = kfifo_out(&port->port_write_buf, packet, size);
        return size;
 }
 
@@ -398,7 +253,7 @@ __acquires(&port->port_lock)
 
                req->length = len;
                list_del(&req->list);
-               req->zero = (gs_buf_data_avail(&port->port_write_buf) == 0);
+               req->zero = kfifo_is_empty(&port->port_write_buf);
 
                pr_vdebug("ttyGS%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
                          port->port_num, len, *((u8 *)req->buf),
@@ -787,10 +642,11 @@ static int gs_open(struct tty_struct *tty, struct file *file)
        spin_lock_irq(&port->port_lock);
 
        /* allocate circular buffer on first open */
-       if (port->port_write_buf.buf_buf == NULL) {
+       if (!kfifo_initialized(&port->port_write_buf)) {
 
                spin_unlock_irq(&port->port_lock);
-               status = gs_buf_alloc(&port->port_write_buf, WRITE_BUF_SIZE);
+               status = kfifo_alloc(&port->port_write_buf,
+                                    WRITE_BUF_SIZE, GFP_KERNEL);
                spin_lock_irq(&port->port_lock);
 
                if (status) {
@@ -839,7 +695,7 @@ static int gs_writes_finished(struct gs_port *p)
 
        /* return true on disconnect or empty buffer */
        spin_lock_irq(&p->port_lock);
-       cond = (p->port_usb == NULL) || !gs_buf_data_avail(&p->port_write_buf);
+       cond = (p->port_usb == NULL) || !kfifo_len(&p->port_write_buf);
        spin_unlock_irq(&p->port_lock);
 
        return cond;
@@ -875,7 +731,7 @@ static void gs_close(struct tty_struct *tty, struct file *file)
        /* wait for circular write buffer to drain, disconnect, or at
         * most GS_CLOSE_TIMEOUT seconds; then discard the rest
         */
-       if (gs_buf_data_avail(&port->port_write_buf) > 0 && gser) {
+       if (kfifo_len(&port->port_write_buf) > 0 && gser) {
                spin_unlock_irq(&port->port_lock);
                wait_event_interruptible_timeout(port->drain_wait,
                                        gs_writes_finished(port),
@@ -889,9 +745,9 @@ static void gs_close(struct tty_struct *tty, struct file *file)
         * let the push tasklet fire again until we're re-opened.
         */
        if (gser == NULL)
-               gs_buf_free(&port->port_write_buf);
+               kfifo_free(&port->port_write_buf);
        else
-               gs_buf_clear(&port->port_write_buf);
+               kfifo_reset(&port->port_write_buf);
 
        port->port.tty = NULL;
 
@@ -915,7 +771,7 @@ static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
 
        spin_lock_irqsave(&port->port_lock, flags);
        if (count)
-               count = gs_buf_put(&port->port_write_buf, buf, count);
+               count = kfifo_in(&port->port_write_buf, buf, count);
        /* treat count == 0 as flush_chars() */
        if (port->port_usb)
                gs_start_tx(port);
@@ -934,7 +790,7 @@ static int gs_put_char(struct tty_struct *tty, unsigned char ch)
                port->port_num, tty, ch, __builtin_return_address(0));
 
        spin_lock_irqsave(&port->port_lock, flags);
-       status = gs_buf_put(&port->port_write_buf, &ch, 1);
+       status = kfifo_put(&port->port_write_buf, ch);
        spin_unlock_irqrestore(&port->port_lock, flags);
 
        return status;
@@ -961,7 +817,7 @@ static int gs_write_room(struct tty_struct *tty)
 
        spin_lock_irqsave(&port->port_lock, flags);
        if (port->port_usb)
-               room = gs_buf_space_avail(&port->port_write_buf);
+               room = kfifo_avail(&port->port_write_buf);
        spin_unlock_irqrestore(&port->port_lock, flags);
 
        pr_vdebug("gs_write_room: (%d,%p) room=%d\n",
@@ -977,7 +833,7 @@ static int gs_chars_in_buffer(struct tty_struct *tty)
        int             chars = 0;
 
        spin_lock_irqsave(&port->port_lock, flags);
-       chars = gs_buf_data_avail(&port->port_write_buf);
+       chars = kfifo_len(&port->port_write_buf);
        spin_unlock_irqrestore(&port->port_lock, flags);
 
        pr_vdebug("gs_chars_in_buffer: (%d,%p) chars=%d\n",
@@ -1148,7 +1004,7 @@ static int gs_console_thread(void *data)
                ep = port->port_usb->in;
 
                spin_lock_irq(&info->con_lock);
-               count = gs_buf_data_avail(&info->con_buf);
+               count = kfifo_len(&info->con_buf);
                size = ep->maxpacket;
 
                if (count > 0 && !info->req_busy) {
@@ -1156,7 +1012,7 @@ static int gs_console_thread(void *data)
                        if (count < size)
                                size = count;
 
-                       xfer = gs_buf_get(&info->con_buf, req->buf, size);
+                       xfer = kfifo_out(&info->con_buf, req->buf, size);
                        req->length = xfer;
 
                        spin_unlock(&info->con_lock);
@@ -1192,7 +1048,7 @@ static int gs_console_setup(struct console *co, char *options)
        info->req_busy = 0;
        spin_lock_init(&info->con_lock);
 
-       status = gs_buf_alloc(&info->con_buf, GS_CONSOLE_BUF_SIZE);
+       status = kfifo_alloc(&info->con_buf, GS_CONSOLE_BUF_SIZE, GFP_KERNEL);
        if (status) {
                pr_err("%s: allocate console buffer failed\n", __func__);
                return status;
@@ -1202,7 +1058,7 @@ static int gs_console_setup(struct console *co, char *options)
                                              co, "gs_console");
        if (IS_ERR(info->console_thread)) {
                pr_err("%s: cannot create console thread\n", __func__);
-               gs_buf_free(&info->con_buf);
+               kfifo_free(&info->con_buf);
                return PTR_ERR(info->console_thread);
        }
        wake_up_process(info->console_thread);
@@ -1217,7 +1073,7 @@ static void gs_console_write(struct console *co,
        unsigned long flags;
 
        spin_lock_irqsave(&info->con_lock, flags);
-       gs_buf_put(&info->con_buf, buf, count);
+       kfifo_in(&info->con_buf, buf, count);
        spin_unlock_irqrestore(&info->con_lock, flags);
 
        wake_up_process(info->console_thread);
@@ -1256,7 +1112,7 @@ static void gserial_console_exit(void)
        unregister_console(&gserial_cons);
        if (!IS_ERR_OR_NULL(info->console_thread))
                kthread_stop(info->console_thread);
-       gs_buf_free(&info->con_buf);
+       kfifo_free(&info->con_buf);
 }
 
 #else
@@ -1529,7 +1385,7 @@ void gserial_disconnect(struct gserial *gser)
        /* finally, free any unused/unusable I/O buffers */
        spin_lock_irqsave(&port->port_lock, flags);
        if (port->port.count == 0 && !port->openclose)
-               gs_buf_free(&port->port_write_buf);
+               kfifo_free(&port->port_write_buf);
        gs_free_requests(gser->out, &port->read_pool, NULL);
        gs_free_requests(gser->out, &port->read_queue, NULL);
        gs_free_requests(gser->in, &port->write_pool, NULL);