Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+14 −165
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@
#include <linux/spinlock.h>
#include <linux/ioctl.h>
#include <linux/serial.h>
#include <linux/circ_buf.h>
#include <linux/kfifo.h>
#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <linux/usb.h>
@@ -40,7 +40,7 @@

/* 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_DESC		"TI USB 3410/5052 Serial Driver"

@@ -82,7 +82,7 @@ struct ti_port {
	spinlock_t		tp_lock;
	int			tp_read_urb_state;
	int			tp_write_urb_in_use;
	struct circ_buf		*tp_write_buf;
	struct kfifo		write_fifo;
};

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);

/* 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 */

@@ -450,8 +441,8 @@ static int ti_startup(struct usb_serial *serial)
		tport->tp_closing_wait = closing_wait;
		init_waitqueue_head(&tport->tp_msr_wait);
		init_waitqueue_head(&tport->tp_write_wait);
		tport->tp_write_buf = ti_buf_alloc();
		if (tport->tp_write_buf == NULL) {
		if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE,
								GFP_KERNEL)) {
			dev_err(&dev->dev, "%s - out of memory\n", __func__);
			kfree(tport);
			status = -ENOMEM;
@@ -468,7 +459,7 @@ static int ti_startup(struct usb_serial *serial)
free_tports:
	for (--i; i >= 0; --i) {
		tport = usb_get_serial_port_data(serial->port[i]);
		ti_buf_free(tport->tp_write_buf);
		kfifo_free(&tport->write_fifo);
		kfree(tport);
		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) {
		tport = usb_get_serial_port_data(serial->port[i]);
		if (tport) {
			ti_buf_free(tport->tp_write_buf);
			kfifo_free(&tport->write_fifo);
			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)
{
	struct ti_port *tport = usb_get_serial_port_data(port);
	unsigned long flags;

	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)
		return -ENODEV;

	spin_lock_irqsave(&tport->tp_lock, flags);
	count = ti_buf_put(tport->tp_write_buf, data, count);
	spin_unlock_irqrestore(&tport->tp_lock, flags);

	count = kfifo_in_locked(&tport->write_fifo, data, count,
							&tport->tp_lock);
	ti_send(tport);

	return count;
@@ -736,7 +724,7 @@ static int ti_write_room(struct tty_struct *tty)
		return 0;

	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);

	dbg("%s - returns %d", __func__, room);
@@ -757,7 +745,7 @@ static int ti_chars_in_buffer(struct tty_struct *tty)
		return 0;

	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);

	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)
		goto unlock;

	count = ti_buf_get(tport->tp_write_buf,
	count = kfifo_out(&tport->write_fifo,
				port->write_urb->transfer_buffer,
				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);
	for (;;) {
		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)
		|| tdev->td_urb_error
		|| 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 */
	if (flush)
		ti_buf_clear(tport->tp_write_buf);
		kfifo_reset_out(&tport->write_fifo);

	spin_unlock_irq(&tport->tp_lock);

@@ -1761,142 +1749,3 @@ static int ti_download_firmware(struct ti_device *tdev)

	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;
}