aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/ftdi_sio.c
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2010-05-05 17:58:13 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 16:21:42 -0400
commitc23e5fc1f7dba228558b4a46e68f7af89515b13c (patch)
treeadd71b10dc2275c98d3439fe3756829c2ec0afc9 /drivers/usb/serial/ftdi_sio.c
parent27c7acf22047fbe4ec4cc36b7c2610dba227697c (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.c59
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);
781static void ftdi_dtr_rts(struct usb_serial_port *port, int on); 781static void ftdi_dtr_rts(struct usb_serial_port *port, int on);
782static void ftdi_process_read_urb(struct urb *urb); 782static void ftdi_process_read_urb(struct urb *urb);
783static int ftdi_prepare_write_buffer(struct usb_serial_port *port, 783static 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);
785static void ftdi_set_termios(struct tty_struct *tty, 785static 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);
787static int ftdi_tiocmget(struct tty_struct *tty, struct file *file); 787static 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 */
1749static int ftdi_prepare_write_buffer(struct usb_serial_port *port, 1738static 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