aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/usb-serial.c
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2010-05-05 17:57:37 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 16:21:42 -0400
commit27c7acf22047fbe4ec4cc36b7c2610dba227697c (patch)
treec0a8f217fc2d7a302b4d2e084bb126e825006ca4 /drivers/usb/serial/usb-serial.c
parent4272568b3dd8dbad36014a107c0fbbef6400c917 (diff)
USB: serial: reimplement generic fifo-based writes
Reimplement fifo-based writes in the generic driver using a multiple pre-allocated urb scheme. In contrast to multi-urb writes, no allocations (of urbs or buffers) are made during run-time and there is less pressure on the host stack queues as currently only two urbs are used (implementation is generic and can handle more than two urbs as well, though). Initial tests using ftdi_sio show that the implementation achieves the same (maximum) throughput at high baudrates as multi-urb writes. The CPU usage is much lower than for multi-urb writes for small write requests and only slightly higher for large (e.g. 2k) requests (due to extra copy via fifo?). Also outperforms multi-urb writes for small write requests on an embedded arm-9 system, where multi-urb writes are CPU-bound at high baudrates (perf reveals that a lot of time is spent in the host stack enqueue function -- could perhaps be a bug as well). Keeping the original write_urb, buffer and flag for now as there are other drivers depending on them. Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
-rw-r--r--drivers/usb/serial/usb-serial.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 8249fd8381fb..941c2d409f85 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -548,8 +548,12 @@ static void usb_serial_port_work(struct work_struct *work)
548 548
549static void kill_traffic(struct usb_serial_port *port) 549static void kill_traffic(struct usb_serial_port *port)
550{ 550{
551 int i;
552
551 usb_kill_urb(port->read_urb); 553 usb_kill_urb(port->read_urb);
552 usb_kill_urb(port->write_urb); 554 usb_kill_urb(port->write_urb);
555 for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
556 usb_kill_urb(port->write_urbs[i]);
553 /* 557 /*
554 * This is tricky. 558 * This is tricky.
555 * Some drivers submit the read_urb in the 559 * Some drivers submit the read_urb in the
@@ -568,6 +572,7 @@ static void kill_traffic(struct usb_serial_port *port)
568static void port_release(struct device *dev) 572static void port_release(struct device *dev)
569{ 573{
570 struct usb_serial_port *port = to_usb_serial_port(dev); 574 struct usb_serial_port *port = to_usb_serial_port(dev);
575 int i;
571 576
572 dbg ("%s - %s", __func__, dev_name(dev)); 577 dbg ("%s - %s", __func__, dev_name(dev));
573 578
@@ -582,6 +587,10 @@ static void port_release(struct device *dev)
582 usb_free_urb(port->write_urb); 587 usb_free_urb(port->write_urb);
583 usb_free_urb(port->interrupt_in_urb); 588 usb_free_urb(port->interrupt_in_urb);
584 usb_free_urb(port->interrupt_out_urb); 589 usb_free_urb(port->interrupt_out_urb);
590 for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) {
591 usb_free_urb(port->write_urbs[i]);
592 kfree(port->bulk_out_buffers[i]);
593 }
585 kfifo_free(&port->write_fifo); 594 kfifo_free(&port->write_fifo);
586 kfree(port->bulk_in_buffer); 595 kfree(port->bulk_in_buffer);
587 kfree(port->bulk_out_buffer); 596 kfree(port->bulk_out_buffer);
@@ -920,6 +929,8 @@ int usb_serial_probe(struct usb_interface *interface,
920 } 929 }
921 930
922 for (i = 0; i < num_bulk_out; ++i) { 931 for (i = 0; i < num_bulk_out; ++i) {
932 int j;
933
923 endpoint = bulk_out_endpoint[i]; 934 endpoint = bulk_out_endpoint[i];
924 port = serial->port[i]; 935 port = serial->port[i];
925 port->write_urb = usb_alloc_urb(0, GFP_KERNEL); 936 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -945,6 +956,28 @@ int usb_serial_probe(struct usb_interface *interface,
945 endpoint->bEndpointAddress), 956 endpoint->bEndpointAddress),
946 port->bulk_out_buffer, buffer_size, 957 port->bulk_out_buffer, buffer_size,
947 serial->type->write_bulk_callback, port); 958 serial->type->write_bulk_callback, port);
959 for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {
960 set_bit(j, &port->write_urbs_free);
961 port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
962 if (!port->write_urbs[j]) {
963 dev_err(&interface->dev,
964 "No free urbs available\n");
965 goto probe_error;
966 }
967 port->bulk_out_buffers[j] = kmalloc(buffer_size,
968 GFP_KERNEL);
969 if (!port->bulk_out_buffers[j]) {
970 dev_err(&interface->dev,
971 "Couldn't allocate bulk_out_buffer\n");
972 goto probe_error;
973 }
974 usb_fill_bulk_urb(port->write_urbs[j], dev,
975 usb_sndbulkpipe(dev,
976 endpoint->bEndpointAddress),
977 port->bulk_out_buffers[j], buffer_size,
978 serial->type->write_bulk_callback,
979 port);
980 }
948 } 981 }
949 982
950 if (serial->type->read_int_callback) { 983 if (serial->type->read_int_callback) {