aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/generic.c')
-rw-r--r--drivers/usb/serial/generic.c59
1 files changed, 39 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 */
264static int usb_serial_generic_write_start(struct usb_serial_port *port) 267static 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;
276retry:
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++;