Commit 074ef65a authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman

USB: ti_usb: use kfifo to implement write buffering

Kill custom fifo implementation.

Compile-only tested.
Signed-off-by: default avatarJohan Hovold <jhovold@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent e421fe97
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/circ_buf.h> #include <linux/kfifo.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/usb.h> #include <linux/usb.h>
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
/* Defines */ /* Defines */
#define TI_DRIVER_VERSION "v0.9" #define TI_DRIVER_VERSION "v0.10"
#define TI_DRIVER_AUTHOR "Al Borchers <alborchers@steinerpoint.com>" #define TI_DRIVER_AUTHOR "Al Borchers <alborchers@steinerpoint.com>"
#define TI_DRIVER_DESC "TI USB 3410/5052 Serial Driver" #define TI_DRIVER_DESC "TI USB 3410/5052 Serial Driver"
...@@ -82,7 +82,7 @@ struct ti_port { ...@@ -82,7 +82,7 @@ struct ti_port {
spinlock_t tp_lock; spinlock_t tp_lock;
int tp_read_urb_state; int tp_read_urb_state;
int tp_write_urb_in_use; int tp_write_urb_in_use;
struct circ_buf *tp_write_buf; struct kfifo write_fifo;
}; };
struct ti_device { struct ti_device {
...@@ -144,15 +144,6 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr, ...@@ -144,15 +144,6 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
static int ti_download_firmware(struct ti_device *tdev); static int ti_download_firmware(struct ti_device *tdev);
/* circular buffer */
static struct circ_buf *ti_buf_alloc(void);
static void ti_buf_free(struct circ_buf *cb);
static void ti_buf_clear(struct circ_buf *cb);
static int ti_buf_data_avail(struct circ_buf *cb);
static int ti_buf_space_avail(struct circ_buf *cb);
static int ti_buf_put(struct circ_buf *cb, const char *buf, int count);
static int ti_buf_get(struct circ_buf *cb, char *buf, int count);
/* Data */ /* Data */
...@@ -450,8 +441,8 @@ static int ti_startup(struct usb_serial *serial) ...@@ -450,8 +441,8 @@ static int ti_startup(struct usb_serial *serial)
tport->tp_closing_wait = closing_wait; tport->tp_closing_wait = closing_wait;
init_waitqueue_head(&tport->tp_msr_wait); init_waitqueue_head(&tport->tp_msr_wait);
init_waitqueue_head(&tport->tp_write_wait); init_waitqueue_head(&tport->tp_write_wait);
tport->tp_write_buf = ti_buf_alloc(); if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE,
if (tport->tp_write_buf == NULL) { GFP_KERNEL)) {
dev_err(&dev->dev, "%s - out of memory\n", __func__); dev_err(&dev->dev, "%s - out of memory\n", __func__);
kfree(tport); kfree(tport);
status = -ENOMEM; status = -ENOMEM;
...@@ -468,7 +459,7 @@ static int ti_startup(struct usb_serial *serial) ...@@ -468,7 +459,7 @@ static int ti_startup(struct usb_serial *serial)
free_tports: free_tports:
for (--i; i >= 0; --i) { for (--i; i >= 0; --i) {
tport = usb_get_serial_port_data(serial->port[i]); tport = usb_get_serial_port_data(serial->port[i]);
ti_buf_free(tport->tp_write_buf); kfifo_free(&tport->write_fifo);
kfree(tport); kfree(tport);
usb_set_serial_port_data(serial->port[i], NULL); usb_set_serial_port_data(serial->port[i], NULL);
} }
...@@ -490,7 +481,7 @@ static void ti_release(struct usb_serial *serial) ...@@ -490,7 +481,7 @@ static void ti_release(struct usb_serial *serial)
for (i = 0; i < serial->num_ports; ++i) { for (i = 0; i < serial->num_ports; ++i) {
tport = usb_get_serial_port_data(serial->port[i]); tport = usb_get_serial_port_data(serial->port[i]);
if (tport) { if (tport) {
ti_buf_free(tport->tp_write_buf); kfifo_free(&tport->write_fifo);
kfree(tport); kfree(tport);
} }
} }
...@@ -701,7 +692,6 @@ static int ti_write(struct tty_struct *tty, struct usb_serial_port *port, ...@@ -701,7 +692,6 @@ static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *data, int count) const unsigned char *data, int count)
{ {
struct ti_port *tport = usb_get_serial_port_data(port); struct ti_port *tport = usb_get_serial_port_data(port);
unsigned long flags;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
...@@ -713,10 +703,8 @@ static int ti_write(struct tty_struct *tty, struct usb_serial_port *port, ...@@ -713,10 +703,8 @@ static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
if (tport == NULL || !tport->tp_is_open) if (tport == NULL || !tport->tp_is_open)
return -ENODEV; return -ENODEV;
spin_lock_irqsave(&tport->tp_lock, flags); count = kfifo_in_locked(&tport->write_fifo, data, count,
count = ti_buf_put(tport->tp_write_buf, data, count); &tport->tp_lock);
spin_unlock_irqrestore(&tport->tp_lock, flags);
ti_send(tport); ti_send(tport);
return count; return count;
...@@ -736,7 +724,7 @@ static int ti_write_room(struct tty_struct *tty) ...@@ -736,7 +724,7 @@ static int ti_write_room(struct tty_struct *tty)
return 0; return 0;
spin_lock_irqsave(&tport->tp_lock, flags); spin_lock_irqsave(&tport->tp_lock, flags);
room = ti_buf_space_avail(tport->tp_write_buf); room = kfifo_avail(&tport->write_fifo);
spin_unlock_irqrestore(&tport->tp_lock, flags); spin_unlock_irqrestore(&tport->tp_lock, flags);
dbg("%s - returns %d", __func__, room); dbg("%s - returns %d", __func__, room);
...@@ -757,7 +745,7 @@ static int ti_chars_in_buffer(struct tty_struct *tty) ...@@ -757,7 +745,7 @@ static int ti_chars_in_buffer(struct tty_struct *tty)
return 0; return 0;
spin_lock_irqsave(&tport->tp_lock, flags); spin_lock_irqsave(&tport->tp_lock, flags);
chars = ti_buf_data_avail(tport->tp_write_buf); chars = kfifo_len(&tport->write_fifo);
spin_unlock_irqrestore(&tport->tp_lock, flags); spin_unlock_irqrestore(&tport->tp_lock, flags);
dbg("%s - returns %d", __func__, chars); dbg("%s - returns %d", __func__, chars);
...@@ -1309,7 +1297,7 @@ static void ti_send(struct ti_port *tport) ...@@ -1309,7 +1297,7 @@ static void ti_send(struct ti_port *tport)
if (tport->tp_write_urb_in_use) if (tport->tp_write_urb_in_use)
goto unlock; goto unlock;
count = ti_buf_get(tport->tp_write_buf, count = kfifo_out(&tport->write_fifo,
port->write_urb->transfer_buffer, port->write_urb->transfer_buffer,
port->bulk_out_size); port->bulk_out_size);
...@@ -1504,7 +1492,7 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush) ...@@ -1504,7 +1492,7 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
add_wait_queue(&tport->tp_write_wait, &wait); add_wait_queue(&tport->tp_write_wait, &wait);
for (;;) { for (;;) {
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (ti_buf_data_avail(tport->tp_write_buf) == 0 if (kfifo_len(&tport->write_fifo) == 0
|| timeout == 0 || signal_pending(current) || timeout == 0 || signal_pending(current)
|| tdev->td_urb_error || tdev->td_urb_error
|| port->serial->disconnected) /* disconnect */ || port->serial->disconnected) /* disconnect */
...@@ -1518,7 +1506,7 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush) ...@@ -1518,7 +1506,7 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
/* flush any remaining data in the buffer */ /* flush any remaining data in the buffer */
if (flush) if (flush)
ti_buf_clear(tport->tp_write_buf); kfifo_reset_out(&tport->write_fifo);
spin_unlock_irq(&tport->tp_lock); spin_unlock_irq(&tport->tp_lock);
...@@ -1761,142 +1749,3 @@ static int ti_download_firmware(struct ti_device *tdev) ...@@ -1761,142 +1749,3 @@ static int ti_download_firmware(struct ti_device *tdev)
return 0; return 0;
} }
/* Circular Buffer Functions */
/*
* ti_buf_alloc
*
* Allocate a circular buffer and all associated memory.
*/
static struct circ_buf *ti_buf_alloc(void)
{
struct circ_buf *cb;
cb = kmalloc(sizeof(struct circ_buf), GFP_KERNEL);
if (cb == NULL)
return NULL;
cb->buf = kmalloc(TI_WRITE_BUF_SIZE, GFP_KERNEL);
if (cb->buf == NULL) {
kfree(cb);
return NULL;
}
ti_buf_clear(cb);
return cb;
}
/*
* ti_buf_free
*
* Free the buffer and all associated memory.
*/
static void ti_buf_free(struct circ_buf *cb)
{
kfree(cb->buf);
kfree(cb);
}
/*
* ti_buf_clear
*
* Clear out all data in the circular buffer.
*/
static void ti_buf_clear(struct circ_buf *cb)
{
cb->head = cb->tail = 0;
}
/*
* ti_buf_data_avail
*
* Return the number of bytes of data available in the circular
* buffer.
*/
static int ti_buf_data_avail(struct circ_buf *cb)
{
return CIRC_CNT(cb->head, cb->tail, TI_WRITE_BUF_SIZE);
}
/*
* ti_buf_space_avail
*
* Return the number of bytes of space available in the circular
* buffer.
*/
static int ti_buf_space_avail(struct circ_buf *cb)
{
return CIRC_SPACE(cb->head, cb->tail, TI_WRITE_BUF_SIZE);
}
/*
* ti_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 int ti_buf_put(struct circ_buf *cb, const char *buf, int count)
{
int c, ret = 0;
while (1) {
c = CIRC_SPACE_TO_END(cb->head, cb->tail, TI_WRITE_BUF_SIZE);
if (count < c)
c = count;
if (c <= 0)
break;
memcpy(cb->buf + cb->head, buf, c);
cb->head = (cb->head + c) & (TI_WRITE_BUF_SIZE-1);
buf += c;
count -= c;
ret += c;
}
return ret;
}
/*
* ti_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 int ti_buf_get(struct circ_buf *cb, char *buf, int count)
{
int c, ret = 0;
while (1) {
c = CIRC_CNT_TO_END(cb->head, cb->tail, TI_WRITE_BUF_SIZE);
if (count < c)
c = count;
if (c <= 0)
break;
memcpy(buf, cb->buf + cb->tail, c);
cb->tail = (cb->tail + c) & (TI_WRITE_BUF_SIZE-1);
buf += c;
count -= c;
ret += c;
}
return ret;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment