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