aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/generic.c
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2010-03-17 18:05:56 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 16:21:34 -0400
commit0f3d5bae2bdacce6c6c1d116809d6b3d50338df7 (patch)
treef0bbd19801f576a26279ee485ff969234a9051b0 /drivers/usb/serial/generic.c
parent2db6c7698bbb37128959d3a207fc46e3f45bef3c (diff)
USB: serial: clean up read processing in generic driver
Always process and flush read urb, but only resubmit when not throttled. The new tty-layer supply plenty of slack so there is really no need to cache and delay processing of a single urb while throttled. Note that unthrottle now submits using GFP_KERNEL as we are not in atomic context (so there is no need to save irq state either). Note also that the process_read_urb function could be added to usb_serial_driver should any driver need to do any device specific processing. Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/generic.c')
-rw-r--r--drivers/usb/serial/generic.c27
1 files changed, 11 insertions, 16 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index ffc2f163bb59..e16c0b234cc9 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -408,16 +408,16 @@ int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,
408} 408}
409EXPORT_SYMBOL_GPL(usb_serial_generic_submit_read_urb); 409EXPORT_SYMBOL_GPL(usb_serial_generic_submit_read_urb);
410 410
411/* Push data to tty layer and resubmit the bulk read URB */ 411static void usb_serial_generic_process_read_urb(struct urb *urb)
412static void flush_and_resubmit_read_urb(struct usb_serial_port *port)
413{ 412{
414 struct urb *urb = port->read_urb; 413 struct usb_serial_port *port = urb->context;
415 struct tty_struct *tty = tty_port_tty_get(&port->port); 414 struct tty_struct *tty;
416 char *ch = (char *)urb->transfer_buffer; 415 char *ch = (char *)urb->transfer_buffer;
417 int i; 416 int i;
418 417
418 tty = tty_port_tty_get(&port->port);
419 if (!tty) 419 if (!tty)
420 goto done; 420 return;
421 421
422 /* The per character mucking around with sysrq path it too slow for 422 /* The per character mucking around with sysrq path it too slow for
423 stuff like 3G modems, so shortcircuit it in the 99.9999999% of cases 423 stuff like 3G modems, so shortcircuit it in the 99.9999999% of cases
@@ -425,7 +425,6 @@ static void flush_and_resubmit_read_urb(struct usb_serial_port *port)
425 if (!port->port.console || !port->sysrq) 425 if (!port->port.console || !port->sysrq)
426 tty_insert_flip_string(tty, ch, urb->actual_length); 426 tty_insert_flip_string(tty, ch, urb->actual_length);
427 else { 427 else {
428 /* Push data to tty */
429 for (i = 0; i < urb->actual_length; i++, ch++) { 428 for (i = 0; i < urb->actual_length; i++, ch++) {
430 if (!usb_serial_handle_sysrq_char(tty, port, *ch)) 429 if (!usb_serial_handle_sysrq_char(tty, port, *ch))
431 tty_insert_flip_char(tty, *ch, TTY_NORMAL); 430 tty_insert_flip_char(tty, *ch, TTY_NORMAL);
@@ -433,8 +432,6 @@ static void flush_and_resubmit_read_urb(struct usb_serial_port *port)
433 } 432 }
434 tty_flip_buffer_push(tty); 433 tty_flip_buffer_push(tty);
435 tty_kref_put(tty); 434 tty_kref_put(tty);
436done:
437 usb_serial_generic_submit_read_urb(port, GFP_ATOMIC);
438} 435}
439 436
440void usb_serial_generic_read_bulk_callback(struct urb *urb) 437void usb_serial_generic_read_bulk_callback(struct urb *urb)
@@ -454,13 +451,14 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
454 451
455 usb_serial_debug_data(debug, &port->dev, __func__, 452 usb_serial_debug_data(debug, &port->dev, __func__,
456 urb->actual_length, data); 453 urb->actual_length, data);
454 usb_serial_generic_process_read_urb(urb);
457 455
458 /* Throttle the device if requested by tty */ 456 /* Throttle the device if requested by tty */
459 spin_lock_irqsave(&port->lock, flags); 457 spin_lock_irqsave(&port->lock, flags);
460 port->throttled = port->throttle_req; 458 port->throttled = port->throttle_req;
461 if (!port->throttled) { 459 if (!port->throttled) {
462 spin_unlock_irqrestore(&port->lock, flags); 460 spin_unlock_irqrestore(&port->lock, flags);
463 flush_and_resubmit_read_urb(port); 461 usb_serial_generic_submit_read_urb(port, GFP_ATOMIC);
464 } else 462 } else
465 spin_unlock_irqrestore(&port->lock, flags); 463 spin_unlock_irqrestore(&port->lock, flags);
466} 464}
@@ -523,20 +521,17 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
523{ 521{
524 struct usb_serial_port *port = tty->driver_data; 522 struct usb_serial_port *port = tty->driver_data;
525 int was_throttled; 523 int was_throttled;
526 unsigned long flags;
527 524
528 dbg("%s - port %d", __func__, port->number); 525 dbg("%s - port %d", __func__, port->number);
529 526
530 /* Clear the throttle flags */ 527 /* Clear the throttle flags */
531 spin_lock_irqsave(&port->lock, flags); 528 spin_lock_irq(&port->lock);
532 was_throttled = port->throttled; 529 was_throttled = port->throttled;
533 port->throttled = port->throttle_req = 0; 530 port->throttled = port->throttle_req = 0;
534 spin_unlock_irqrestore(&port->lock, flags); 531 spin_unlock_irq(&port->lock);
535 532
536 if (was_throttled) { 533 if (was_throttled)
537 /* Resume reading from device */ 534 usb_serial_generic_submit_read_urb(port, GFP_KERNEL);
538 flush_and_resubmit_read_urb(port);
539 }
540} 535}
541 536
542#ifdef CONFIG_MAGIC_SYSRQ 537#ifdef CONFIG_MAGIC_SYSRQ