diff options
author | Johan Hovold <jhovold@gmail.com> | 2010-05-05 17:58:13 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-20 16:21:42 -0400 |
commit | c23e5fc1f7dba228558b4a46e68f7af89515b13c (patch) | |
tree | add71b10dc2275c98d3439fe3756829c2ec0afc9 /drivers/usb/serial/ftdi_sio.c | |
parent | 27c7acf22047fbe4ec4cc36b7c2610dba227697c (diff) |
USB: serial: remove multi-urb write from generic driver
Remove multi-urb write from the generic driver and simplify the
prepare_write_buffer prototype:
int (*prepare_write_buffer)(struct usb_serial_port *port,
void *dest, size_t size);
The default implementation simply fills dest with data from port write
fifo but drivers can override it if they need to process the outgoing
data (e.g. add headers).
Turn ftdi_sio into a generic fifo-based driver, which lowers CPU usage
significantly for small writes while retaining maximum throughput.
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 59 |
1 files changed, 21 insertions, 38 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f515f32cde68..14f7a34d614c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -781,7 +781,7 @@ static void ftdi_close(struct usb_serial_port *port); | |||
781 | static void ftdi_dtr_rts(struct usb_serial_port *port, int on); | 781 | static void ftdi_dtr_rts(struct usb_serial_port *port, int on); |
782 | static void ftdi_process_read_urb(struct urb *urb); | 782 | static void ftdi_process_read_urb(struct urb *urb); |
783 | static int ftdi_prepare_write_buffer(struct usb_serial_port *port, | 783 | static int ftdi_prepare_write_buffer(struct usb_serial_port *port, |
784 | void **dest, size_t size, const void *buf, size_t count); | 784 | void *dest, size_t size); |
785 | static void ftdi_set_termios(struct tty_struct *tty, | 785 | static void ftdi_set_termios(struct tty_struct *tty, |
786 | struct usb_serial_port *port, struct ktermios *old); | 786 | struct usb_serial_port *port, struct ktermios *old); |
787 | static int ftdi_tiocmget(struct tty_struct *tty, struct file *file); | 787 | static int ftdi_tiocmget(struct tty_struct *tty, struct file *file); |
@@ -808,8 +808,7 @@ static struct usb_serial_driver ftdi_sio_device = { | |||
808 | .id_table = id_table_combined, | 808 | .id_table = id_table_combined, |
809 | .num_ports = 1, | 809 | .num_ports = 1, |
810 | .bulk_in_size = 512, | 810 | .bulk_in_size = 512, |
811 | /* Must modify prepare_write_buffer if multi_urb_write is changed. */ | 811 | .bulk_out_size = 256, |
812 | .multi_urb_write = 1, | ||
813 | .probe = ftdi_sio_probe, | 812 | .probe = ftdi_sio_probe, |
814 | .port_probe = ftdi_sio_port_probe, | 813 | .port_probe = ftdi_sio_port_probe, |
815 | .port_remove = ftdi_sio_port_remove, | 814 | .port_remove = ftdi_sio_port_remove, |
@@ -1531,15 +1530,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) | |||
1531 | quirk->port_probe(priv); | 1530 | quirk->port_probe(priv); |
1532 | 1531 | ||
1533 | priv->port = port; | 1532 | priv->port = port; |
1534 | |||
1535 | /* Free port's existing write urb and transfer buffer. */ | ||
1536 | if (port->write_urb) { | ||
1537 | usb_free_urb(port->write_urb); | ||
1538 | port->write_urb = NULL; | ||
1539 | } | ||
1540 | kfree(port->bulk_out_buffer); | ||
1541 | port->bulk_out_buffer = NULL; | ||
1542 | |||
1543 | usb_set_serial_port_data(port, priv); | 1533 | usb_set_serial_port_data(port, priv); |
1544 | 1534 | ||
1545 | ftdi_determine_type(port); | 1535 | ftdi_determine_type(port); |
@@ -1734,8 +1724,7 @@ static void ftdi_close(struct usb_serial_port *port) | |||
1734 | 1724 | ||
1735 | dbg("%s", __func__); | 1725 | dbg("%s", __func__); |
1736 | 1726 | ||
1737 | /* shutdown our bulk read */ | 1727 | usb_serial_generic_close(port); |
1738 | usb_kill_urb(port->read_urb); | ||
1739 | kref_put(&priv->kref, ftdi_sio_priv_release); | 1728 | kref_put(&priv->kref, ftdi_sio_priv_release); |
1740 | } | 1729 | } |
1741 | 1730 | ||
@@ -1747,40 +1736,34 @@ static void ftdi_close(struct usb_serial_port *port) | |||
1747 | * The new devices do not require this byte | 1736 | * The new devices do not require this byte |
1748 | */ | 1737 | */ |
1749 | static int ftdi_prepare_write_buffer(struct usb_serial_port *port, | 1738 | static int ftdi_prepare_write_buffer(struct usb_serial_port *port, |
1750 | void **dest, size_t size, const void *src, size_t count) | 1739 | void *dest, size_t size) |
1751 | { | 1740 | { |
1752 | struct ftdi_private *priv; | 1741 | struct ftdi_private *priv; |
1753 | unsigned char *buffer; | 1742 | int count; |
1754 | int len; | 1743 | unsigned long flags; |
1755 | 1744 | ||
1756 | priv = usb_get_serial_port_data(port); | 1745 | priv = usb_get_serial_port_data(port); |
1757 | 1746 | ||
1758 | len = count; | ||
1759 | if (priv->chip_type == SIO && count != 0) | ||
1760 | len += ((count - 1) / (priv->max_packet_size - 1)) + 1; | ||
1761 | |||
1762 | buffer = kmalloc(len, GFP_ATOMIC); | ||
1763 | if (!buffer) { | ||
1764 | dev_err(&port->dev, "%s - could not allocate buffer\n", | ||
1765 | __func__); | ||
1766 | return -ENOMEM; | ||
1767 | } | ||
1768 | |||
1769 | if (priv->chip_type == SIO) { | 1747 | if (priv->chip_type == SIO) { |
1770 | int i, msg_len; | 1748 | unsigned char *buffer = dest; |
1771 | 1749 | int i, len, c; | |
1772 | for (i = 0; i < len; i += priv->max_packet_size) { | 1750 | |
1773 | msg_len = min_t(int, len - i, priv->max_packet_size) - 1; | 1751 | count = 0; |
1774 | buffer[i] = (msg_len << 2) + 1; | 1752 | spin_lock_irqsave(&port->lock, flags); |
1775 | memcpy(&buffer[i + 1], src, msg_len); | 1753 | for (i = 0; i < size - 1; i += priv->max_packet_size) { |
1776 | src += msg_len; | 1754 | len = min_t(int, size - i, priv->max_packet_size) - 1; |
1755 | buffer[i] = (len << 2) + 1; | ||
1756 | c = kfifo_out(&port->write_fifo, &buffer[i + 1], len); | ||
1757 | if (!c) | ||
1758 | break; | ||
1759 | count += c + 1; | ||
1777 | } | 1760 | } |
1761 | spin_unlock_irqrestore(&port->lock, flags); | ||
1778 | } else { | 1762 | } else { |
1779 | memcpy(buffer, src, count); | 1763 | count = kfifo_out_locked(&port->write_fifo, dest, size, |
1764 | &port->lock); | ||
1780 | } | 1765 | } |
1781 | 1766 | ||
1782 | *dest = buffer; | ||
1783 | |||
1784 | return count; | 1767 | return count; |
1785 | } | 1768 | } |
1786 | 1769 | ||