USB: ti_usb: use kfifo to implement write buffering
Kill custom fifo implementation. Compile-only tested. Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
e421fe97ad
commit
074ef65aac
@ -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 @@
|
|||||||
|
|
||||||
/* 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 {
|
|||||||
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,
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user