diff options
Diffstat (limited to 'drivers/usb/serial/generic.c')
-rw-r--r-- | drivers/usb/serial/generic.c | 61 |
1 files changed, 42 insertions, 19 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index b63ce023f96f..1bd192290b08 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -332,9 +332,9 @@ void usb_serial_generic_process_read_urb(struct urb *urb) | |||
332 | * stuff like 3G modems, so shortcircuit it in the 99.9999999% of | 332 | * stuff like 3G modems, so shortcircuit it in the 99.9999999% of |
333 | * cases where the USB serial is not a console anyway. | 333 | * cases where the USB serial is not a console anyway. |
334 | */ | 334 | */ |
335 | if (!port->port.console || !port->sysrq) | 335 | if (!port->port.console || !port->sysrq) { |
336 | tty_insert_flip_string(&port->port, ch, urb->actual_length); | 336 | tty_insert_flip_string(&port->port, ch, urb->actual_length); |
337 | else { | 337 | } else { |
338 | for (i = 0; i < urb->actual_length; i++, ch++) { | 338 | for (i = 0; i < urb->actual_length; i++, ch++) { |
339 | if (!usb_serial_handle_sysrq_char(port, *ch)) | 339 | if (!usb_serial_handle_sysrq_char(port, *ch)) |
340 | tty_insert_flip_char(&port->port, *ch, TTY_NORMAL); | 340 | tty_insert_flip_char(&port->port, *ch, TTY_NORMAL); |
@@ -359,24 +359,38 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb) | |||
359 | 359 | ||
360 | dev_dbg(&port->dev, "%s - urb %d, len %d\n", __func__, i, | 360 | dev_dbg(&port->dev, "%s - urb %d, len %d\n", __func__, i, |
361 | urb->actual_length); | 361 | urb->actual_length); |
362 | 362 | switch (urb->status) { | |
363 | if (urb->status) { | 363 | case 0: |
364 | dev_dbg(&port->dev, "%s - non-zero urb status: %d\n", | 364 | break; |
365 | __func__, urb->status); | 365 | case -ENOENT: |
366 | case -ECONNRESET: | ||
367 | case -ESHUTDOWN: | ||
368 | dev_dbg(&port->dev, "%s - urb stopped: %d\n", | ||
369 | __func__, urb->status); | ||
366 | return; | 370 | return; |
371 | case -EPIPE: | ||
372 | dev_err(&port->dev, "%s - urb stopped: %d\n", | ||
373 | __func__, urb->status); | ||
374 | return; | ||
375 | default: | ||
376 | dev_err(&port->dev, "%s - nonzero urb status: %d\n", | ||
377 | __func__, urb->status); | ||
378 | goto resubmit; | ||
367 | } | 379 | } |
368 | 380 | ||
369 | usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); | 381 | usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); |
370 | port->serial->type->process_read_urb(urb); | 382 | port->serial->type->process_read_urb(urb); |
371 | 383 | ||
384 | resubmit: | ||
372 | /* Throttle the device if requested by tty */ | 385 | /* Throttle the device if requested by tty */ |
373 | spin_lock_irqsave(&port->lock, flags); | 386 | spin_lock_irqsave(&port->lock, flags); |
374 | port->throttled = port->throttle_req; | 387 | port->throttled = port->throttle_req; |
375 | if (!port->throttled) { | 388 | if (!port->throttled) { |
376 | spin_unlock_irqrestore(&port->lock, flags); | 389 | spin_unlock_irqrestore(&port->lock, flags); |
377 | usb_serial_generic_submit_read_urb(port, i, GFP_ATOMIC); | 390 | usb_serial_generic_submit_read_urb(port, i, GFP_ATOMIC); |
378 | } else | 391 | } else { |
379 | spin_unlock_irqrestore(&port->lock, flags); | 392 | spin_unlock_irqrestore(&port->lock, flags); |
393 | } | ||
380 | } | 394 | } |
381 | EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); | 395 | EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); |
382 | 396 | ||
@@ -384,29 +398,38 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb) | |||
384 | { | 398 | { |
385 | unsigned long flags; | 399 | unsigned long flags; |
386 | struct usb_serial_port *port = urb->context; | 400 | struct usb_serial_port *port = urb->context; |
387 | int status = urb->status; | ||
388 | int i; | 401 | int i; |
389 | 402 | ||
390 | for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) | 403 | for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) { |
391 | if (port->write_urbs[i] == urb) | 404 | if (port->write_urbs[i] == urb) |
392 | break; | 405 | break; |
393 | 406 | } | |
394 | spin_lock_irqsave(&port->lock, flags); | 407 | spin_lock_irqsave(&port->lock, flags); |
395 | port->tx_bytes -= urb->transfer_buffer_length; | 408 | port->tx_bytes -= urb->transfer_buffer_length; |
396 | set_bit(i, &port->write_urbs_free); | 409 | set_bit(i, &port->write_urbs_free); |
397 | spin_unlock_irqrestore(&port->lock, flags); | 410 | spin_unlock_irqrestore(&port->lock, flags); |
398 | 411 | ||
399 | if (status) { | 412 | switch (urb->status) { |
400 | dev_dbg(&port->dev, "%s - non-zero urb status: %d\n", | 413 | case 0: |
401 | __func__, status); | 414 | break; |
402 | 415 | case -ENOENT: | |
403 | spin_lock_irqsave(&port->lock, flags); | 416 | case -ECONNRESET: |
404 | kfifo_reset_out(&port->write_fifo); | 417 | case -ESHUTDOWN: |
405 | spin_unlock_irqrestore(&port->lock, flags); | 418 | dev_dbg(&port->dev, "%s - urb stopped: %d\n", |
406 | } else { | 419 | __func__, urb->status); |
407 | usb_serial_generic_write_start(port, GFP_ATOMIC); | 420 | return; |
421 | case -EPIPE: | ||
422 | dev_err_console(port, "%s - urb stopped: %d\n", | ||
423 | __func__, urb->status); | ||
424 | return; | ||
425 | default: | ||
426 | dev_err_console(port, "%s - nonzero urb status: %d\n", | ||
427 | __func__, urb->status); | ||
428 | goto resubmit; | ||
408 | } | 429 | } |
409 | 430 | ||
431 | resubmit: | ||
432 | usb_serial_generic_write_start(port, GFP_ATOMIC); | ||
410 | usb_serial_port_softint(port); | 433 | usb_serial_port_softint(port); |
411 | } | 434 | } |
412 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); | 435 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); |