diff options
author | Elina Pasheva <epasheva@sierrawireless.com> | 2009-04-29 13:29:21 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-06-16 00:44:45 -0400 |
commit | b0cda8c5f7b652c6c27bcb3891d174534d2f1a91 (patch) | |
tree | 8f72962f8fb4bc88e8d21dda0369fe4e08169d2a /drivers/usb/serial | |
parent | 40d2ff32f102e69d482480265ec60ffb86b028de (diff) |
USB: serial: sierra driver read path bug fix
This patch fixes a problem in function sierra_indat_callback() which
would stop receiving traffic from a modem if a number of URB failures
occur. Failed URBs are not resubmitted for the next read and there is
only a limited number of URBs allocated for the IN path. After this
number of failures, the receive path stops working on a particular
interface.
Signed-off-by: Elina Pasheva <epasheva@sierrawireless.com>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/sierra.c | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 27f41f95aefb..f494c5f659e2 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -509,10 +509,10 @@ static void sierra_indat_callback(struct urb *urb) | |||
509 | unsigned char *data = urb->transfer_buffer; | 509 | unsigned char *data = urb->transfer_buffer; |
510 | int status = urb->status; | 510 | int status = urb->status; |
511 | 511 | ||
512 | dbg("%s: %p", __func__, urb); | ||
513 | |||
514 | endpoint = usb_pipeendpoint(urb->pipe); | 512 | endpoint = usb_pipeendpoint(urb->pipe); |
515 | port = urb->context; | 513 | port = urb->context; |
514 | |||
515 | dev_dbg(&port->dev, "%s: %p\n", __func__, urb); | ||
516 | 516 | ||
517 | if (status) { | 517 | if (status) { |
518 | dev_dbg(&port->dev, "%s: nonzero status: %d on" | 518 | dev_dbg(&port->dev, "%s: nonzero status: %d on" |
@@ -520,22 +520,28 @@ static void sierra_indat_callback(struct urb *urb) | |||
520 | } else { | 520 | } else { |
521 | if (urb->actual_length) { | 521 | if (urb->actual_length) { |
522 | tty = tty_port_tty_get(&port->port); | 522 | tty = tty_port_tty_get(&port->port); |
523 | |||
523 | tty_buffer_request_room(tty, urb->actual_length); | 524 | tty_buffer_request_room(tty, urb->actual_length); |
524 | tty_insert_flip_string(tty, data, urb->actual_length); | 525 | tty_insert_flip_string(tty, data, urb->actual_length); |
525 | tty_flip_buffer_push(tty); | 526 | tty_flip_buffer_push(tty); |
527 | |||
526 | tty_kref_put(tty); | 528 | tty_kref_put(tty); |
527 | } else | 529 | usb_serial_debug_data(debug, &port->dev, __func__, |
530 | urb->actual_length, data); | ||
531 | } else { | ||
528 | dev_dbg(&port->dev, "%s: empty read urb" | 532 | dev_dbg(&port->dev, "%s: empty read urb" |
529 | " received\n", __func__); | 533 | " received\n", __func__); |
530 | |||
531 | /* Resubmit urb so we continue receiving */ | ||
532 | if (port->port.count && status != -ESHUTDOWN && status != -EPERM) { | ||
533 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
534 | if (err) | ||
535 | dev_err(&port->dev, "resubmit read urb failed." | ||
536 | "(%d)\n", err); | ||
537 | } | 534 | } |
538 | } | 535 | } |
536 | |||
537 | /* Resubmit urb so we continue receiving */ | ||
538 | if (port->port.count && status != -ESHUTDOWN && status != -EPERM) { | ||
539 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
540 | if (err) | ||
541 | dev_err(&port->dev, "resubmit read urb failed." | ||
542 | "(%d)\n", err); | ||
543 | } | ||
544 | |||
539 | return; | 545 | return; |
540 | } | 546 | } |
541 | 547 | ||