diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/generic.c | 59 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 33 |
2 files changed, 72 insertions, 20 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 1a134f9c64f3..3ae17840175c 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * USB Serial Converter Generic functions | 2 | * USB Serial Converter Generic functions |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com) | ||
4 | * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) | 5 | * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) |
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
@@ -143,6 +144,7 @@ static void generic_cleanup(struct usb_serial_port *port) | |||
143 | { | 144 | { |
144 | struct usb_serial *serial = port->serial; | 145 | struct usb_serial *serial = port->serial; |
145 | unsigned long flags; | 146 | unsigned long flags; |
147 | int i; | ||
146 | 148 | ||
147 | dbg("%s - port %d", __func__, port->number); | 149 | dbg("%s - port %d", __func__, port->number); |
148 | 150 | ||
@@ -150,6 +152,8 @@ static void generic_cleanup(struct usb_serial_port *port) | |||
150 | /* shutdown any bulk transfers that might be going on */ | 152 | /* shutdown any bulk transfers that might be going on */ |
151 | if (port->bulk_out_size) { | 153 | if (port->bulk_out_size) { |
152 | usb_kill_urb(port->write_urb); | 154 | usb_kill_urb(port->write_urb); |
155 | for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) | ||
156 | usb_kill_urb(port->write_urbs[i]); | ||
153 | 157 | ||
154 | spin_lock_irqsave(&port->lock, flags); | 158 | spin_lock_irqsave(&port->lock, flags); |
155 | kfifo_reset_out(&port->write_fifo); | 159 | kfifo_reset_out(&port->write_fifo); |
@@ -258,46 +262,56 @@ err_urb: | |||
258 | * usb_serial_generic_write_start - kick off an URB write | 262 | * usb_serial_generic_write_start - kick off an URB write |
259 | * @port: Pointer to the &struct usb_serial_port data | 263 | * @port: Pointer to the &struct usb_serial_port data |
260 | * | 264 | * |
261 | * Returns the number of bytes queued on success. This will be zero if there | 265 | * Returns zero on success, or a negative errno value |
262 | * was nothing to send. Otherwise, it returns a negative errno value | ||
263 | */ | 266 | */ |
264 | static int usb_serial_generic_write_start(struct usb_serial_port *port) | 267 | static int usb_serial_generic_write_start(struct usb_serial_port *port) |
265 | { | 268 | { |
266 | int result; | 269 | struct urb *urb; |
267 | int count; | 270 | int count, result; |
268 | unsigned long flags; | 271 | unsigned long flags; |
272 | int i; | ||
269 | 273 | ||
274 | if (test_and_set_bit_lock(USB_SERIAL_WRITE_BUSY, &port->flags)) | ||
275 | return 0; | ||
276 | retry: | ||
270 | spin_lock_irqsave(&port->lock, flags); | 277 | spin_lock_irqsave(&port->lock, flags); |
271 | if (port->write_urb_busy || !kfifo_len(&port->write_fifo)) { | 278 | if (!port->write_urbs_free || !kfifo_len(&port->write_fifo)) { |
279 | clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); | ||
272 | spin_unlock_irqrestore(&port->lock, flags); | 280 | spin_unlock_irqrestore(&port->lock, flags); |
273 | return 0; | 281 | return 0; |
274 | } | 282 | } |
275 | port->write_urb_busy = 1; | 283 | i = (int)find_first_bit(&port->write_urbs_free, |
284 | ARRAY_SIZE(port->write_urbs)); | ||
276 | spin_unlock_irqrestore(&port->lock, flags); | 285 | spin_unlock_irqrestore(&port->lock, flags); |
277 | 286 | ||
287 | urb = port->write_urbs[i]; | ||
278 | count = port->serial->type->prepare_write_buffer(port, | 288 | count = port->serial->type->prepare_write_buffer(port, |
279 | &port->write_urb->transfer_buffer, | 289 | &urb->transfer_buffer, |
280 | port->bulk_out_size, NULL, 0); | 290 | port->bulk_out_size, NULL, 0); |
281 | usb_serial_debug_data(debug, &port->dev, __func__, | 291 | urb->transfer_buffer_length = count; |
282 | count, port->write_urb->transfer_buffer); | 292 | usb_serial_debug_data(debug, &port->dev, __func__, count, |
283 | port->write_urb->transfer_buffer_length = count; | 293 | urb->transfer_buffer); |
284 | 294 | result = usb_submit_urb(urb, GFP_ATOMIC); | |
285 | /* send the data out the bulk port */ | ||
286 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | ||
287 | if (result) { | 295 | if (result) { |
288 | dev_err(&port->dev, "%s - error submitting urb: %d\n", | 296 | dev_err(&port->dev, "%s - error submitting urb: %d\n", |
289 | __func__, result); | 297 | __func__, result); |
290 | /* don't have to grab the lock here, as we will | 298 | clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); |
291 | retry if != 0 */ | ||
292 | port->write_urb_busy = 0; | ||
293 | return result; | 299 | return result; |
294 | } | 300 | } |
301 | clear_bit(i, &port->write_urbs_free); | ||
295 | 302 | ||
296 | spin_lock_irqsave(&port->lock, flags); | 303 | spin_lock_irqsave(&port->lock, flags); |
297 | port->tx_bytes += count; | 304 | port->tx_bytes += count; |
298 | spin_unlock_irqrestore(&port->lock, flags); | 305 | spin_unlock_irqrestore(&port->lock, flags); |
299 | 306 | ||
300 | return count; | 307 | /* Try sending off another urb, unless in irq context (in which case |
308 | * there will be no free urb). */ | ||
309 | if (!in_irq()) | ||
310 | goto retry; | ||
311 | |||
312 | clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); | ||
313 | |||
314 | return 0; | ||
301 | } | 315 | } |
302 | 316 | ||
303 | /** | 317 | /** |
@@ -461,6 +475,7 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb) | |||
461 | unsigned long flags; | 475 | unsigned long flags; |
462 | struct usb_serial_port *port = urb->context; | 476 | struct usb_serial_port *port = urb->context; |
463 | int status = urb->status; | 477 | int status = urb->status; |
478 | int i; | ||
464 | 479 | ||
465 | dbg("%s - port %d", __func__, port->number); | 480 | dbg("%s - port %d", __func__, port->number); |
466 | 481 | ||
@@ -472,9 +487,13 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb) | |||
472 | port->tx_urbs--; | 487 | port->tx_urbs--; |
473 | spin_unlock_irqrestore(&port->lock, flags); | 488 | spin_unlock_irqrestore(&port->lock, flags); |
474 | } else { | 489 | } else { |
490 | for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) | ||
491 | if (port->write_urbs[i] == urb) | ||
492 | break; | ||
493 | |||
475 | spin_lock_irqsave(&port->lock, flags); | 494 | spin_lock_irqsave(&port->lock, flags); |
476 | port->tx_bytes -= urb->transfer_buffer_length; | 495 | port->tx_bytes -= urb->transfer_buffer_length; |
477 | port->write_urb_busy = 0; | 496 | set_bit(i, &port->write_urbs_free); |
478 | spin_unlock_irqrestore(&port->lock, flags); | 497 | spin_unlock_irqrestore(&port->lock, flags); |
479 | 498 | ||
480 | if (status) { | 499 | if (status) { |
@@ -576,7 +595,7 @@ int usb_serial_generic_resume(struct usb_serial *serial) | |||
576 | c++; | 595 | c++; |
577 | } | 596 | } |
578 | 597 | ||
579 | if (port->write_urb) { | 598 | if (port->bulk_out_size) { |
580 | r = usb_serial_generic_write_start(port); | 599 | r = usb_serial_generic_write_start(port); |
581 | if (r < 0) | 600 | if (r < 0) |
582 | c++; | 601 | c++; |
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 | ||
549 | static void kill_traffic(struct usb_serial_port *port) | 549 | static 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) | |||
568 | static void port_release(struct device *dev) | 572 | static 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) { |