aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/generic.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-05-08 13:03:52 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-05-08 13:03:52 -0400
commit132d68d37d33f1d0b9c1f507c8b4d64c27ecec8a (patch)
treeb3c05972e5579e1574873fe745fb1358c62a269c /drivers/usb/serial/generic.c
parent80f232121b69cc69a31ccb2b38c1665d770b0710 (diff)
parent3515468a87a47781f6af818773650513ff14656a (diff)
Merge tag 'usb-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB/PHY updates from Greg KH: "Here is the big set of USB and PHY driver patches for 5.2-rc1 There is the usual set of: - USB gadget updates - PHY driver updates and additions - USB serial driver updates and fixes - typec updates and new chips supported - mtu3 driver updates - xhci driver updates - other tiny driver updates Nothing really interesting, just constant forward progress. All of these have been in linux-next for a while with no reported issues. The usb-gadget and usb-serial trees were merged a bit "late", but both of them had been in linux-next before they got merged here last Friday" * tag 'usb-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (206 commits) USB: serial: f81232: implement break control USB: serial: f81232: add high baud rate support USB: serial: f81232: clear overrun flag USB: serial: f81232: fix interrupt worker not stop usb: dwc3: Rename DWC3_DCTL_LPM_ERRATA usb: dwc3: Fix default lpm_nyet_threshold value usb: dwc3: debug: Print GET_STATUS(device) tracepoint usb: dwc3: Do core validation early on probe usb: dwc3: gadget: Set lpm_capable usb: gadget: atmel: tie wake lock to running clock usb: gadget: atmel: support USB suspend usb: gadget: atmel_usba_udc: simplify setting of interrupt-enabled mask dwc2: gadget: Fix completed transfer size calculation in DDMA usb: dwc2: Set lpm mode parameters depend on HW configuration usb: dwc2: Fix channel disable flow usb: dwc2: Set actual frame number for completed ISOC transfer usb: gadget: do not use __constant_cpu_to_le16 usb: dwc2: gadget: Increase descriptors count for ISOC's usb: introduce usb_ep_type_string() function usb: dwc3: move synchronize_irq() out of the spinlock protected block ...
Diffstat (limited to 'drivers/usb/serial/generic.c')
-rw-r--r--drivers/usb/serial/generic.c76
1 files changed, 41 insertions, 35 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 2274d9625f63..1be8bea372a2 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -106,12 +106,8 @@ void usb_serial_generic_deregister(void)
106int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port) 106int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port)
107{ 107{
108 int result = 0; 108 int result = 0;
109 unsigned long flags;
110 109
111 spin_lock_irqsave(&port->lock, flags); 110 clear_bit(USB_SERIAL_THROTTLED, &port->flags);
112 port->throttled = 0;
113 port->throttle_req = 0;
114 spin_unlock_irqrestore(&port->lock, flags);
115 111
116 if (port->bulk_in_size) 112 if (port->bulk_in_size)
117 result = usb_serial_generic_submit_read_urbs(port, GFP_KERNEL); 113 result = usb_serial_generic_submit_read_urbs(port, GFP_KERNEL);
@@ -375,7 +371,7 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
375{ 371{
376 struct usb_serial_port *port = urb->context; 372 struct usb_serial_port *port = urb->context;
377 unsigned char *data = urb->transfer_buffer; 373 unsigned char *data = urb->transfer_buffer;
378 unsigned long flags; 374 bool stopped = false;
379 int status = urb->status; 375 int status = urb->status;
380 int i; 376 int i;
381 377
@@ -383,42 +379,55 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
383 if (urb == port->read_urbs[i]) 379 if (urb == port->read_urbs[i])
384 break; 380 break;
385 } 381 }
386 set_bit(i, &port->read_urbs_free);
387 382
388 dev_dbg(&port->dev, "%s - urb %d, len %d\n", __func__, i, 383 dev_dbg(&port->dev, "%s - urb %d, len %d\n", __func__, i,
389 urb->actual_length); 384 urb->actual_length);
390 switch (status) { 385 switch (status) {
391 case 0: 386 case 0:
387 usb_serial_debug_data(&port->dev, __func__, urb->actual_length,
388 data);
389 port->serial->type->process_read_urb(urb);
392 break; 390 break;
393 case -ENOENT: 391 case -ENOENT:
394 case -ECONNRESET: 392 case -ECONNRESET:
395 case -ESHUTDOWN: 393 case -ESHUTDOWN:
396 dev_dbg(&port->dev, "%s - urb stopped: %d\n", 394 dev_dbg(&port->dev, "%s - urb stopped: %d\n",
397 __func__, status); 395 __func__, status);
398 return; 396 stopped = true;
397 break;
399 case -EPIPE: 398 case -EPIPE:
400 dev_err(&port->dev, "%s - urb stopped: %d\n", 399 dev_err(&port->dev, "%s - urb stopped: %d\n",
401 __func__, status); 400 __func__, status);
402 return; 401 stopped = true;
402 break;
403 default: 403 default:
404 dev_dbg(&port->dev, "%s - nonzero urb status: %d\n", 404 dev_dbg(&port->dev, "%s - nonzero urb status: %d\n",
405 __func__, status); 405 __func__, status);
406 goto resubmit; 406 break;
407 } 407 }
408 408
409 usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); 409 /*
410 port->serial->type->process_read_urb(urb); 410 * Make sure URB processing is done before marking as free to avoid
411 * racing with unthrottle() on another CPU. Matches the barriers
412 * implied by the test_and_clear_bit() in
413 * usb_serial_generic_submit_read_urb().
414 */
415 smp_mb__before_atomic();
416 set_bit(i, &port->read_urbs_free);
417 /*
418 * Make sure URB is marked as free before checking the throttled flag
419 * to avoid racing with unthrottle() on another CPU. Matches the
420 * smp_mb() in unthrottle().
421 */
422 smp_mb__after_atomic();
411 423
412resubmit: 424 if (stopped)
413 /* Throttle the device if requested by tty */ 425 return;
414 spin_lock_irqsave(&port->lock, flags); 426
415 port->throttled = port->throttle_req; 427 if (test_bit(USB_SERIAL_THROTTLED, &port->flags))
416 if (!port->throttled) { 428 return;
417 spin_unlock_irqrestore(&port->lock, flags); 429
418 usb_serial_generic_submit_read_urb(port, i, GFP_ATOMIC); 430 usb_serial_generic_submit_read_urb(port, i, GFP_ATOMIC);
419 } else {
420 spin_unlock_irqrestore(&port->lock, flags);
421 }
422} 431}
423EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); 432EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
424 433
@@ -454,10 +463,9 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb)
454 default: 463 default:
455 dev_err_console(port, "%s - nonzero urb status: %d\n", 464 dev_err_console(port, "%s - nonzero urb status: %d\n",
456 __func__, status); 465 __func__, status);
457 goto resubmit; 466 break;
458 } 467 }
459 468
460resubmit:
461 usb_serial_generic_write_start(port, GFP_ATOMIC); 469 usb_serial_generic_write_start(port, GFP_ATOMIC);
462 usb_serial_port_softint(port); 470 usb_serial_port_softint(port);
463} 471}
@@ -466,26 +474,24 @@ EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
466void usb_serial_generic_throttle(struct tty_struct *tty) 474void usb_serial_generic_throttle(struct tty_struct *tty)
467{ 475{
468 struct usb_serial_port *port = tty->driver_data; 476 struct usb_serial_port *port = tty->driver_data;
469 unsigned long flags;
470 477
471 spin_lock_irqsave(&port->lock, flags); 478 set_bit(USB_SERIAL_THROTTLED, &port->flags);
472 port->throttle_req = 1;
473 spin_unlock_irqrestore(&port->lock, flags);
474} 479}
475EXPORT_SYMBOL_GPL(usb_serial_generic_throttle); 480EXPORT_SYMBOL_GPL(usb_serial_generic_throttle);
476 481
477void usb_serial_generic_unthrottle(struct tty_struct *tty) 482void usb_serial_generic_unthrottle(struct tty_struct *tty)
478{ 483{
479 struct usb_serial_port *port = tty->driver_data; 484 struct usb_serial_port *port = tty->driver_data;
480 int was_throttled;
481 485
482 spin_lock_irq(&port->lock); 486 clear_bit(USB_SERIAL_THROTTLED, &port->flags);
483 was_throttled = port->throttled; 487
484 port->throttled = port->throttle_req = 0; 488 /*
485 spin_unlock_irq(&port->lock); 489 * Matches the smp_mb__after_atomic() in
490 * usb_serial_generic_read_bulk_callback().
491 */
492 smp_mb();
486 493
487 if (was_throttled) 494 usb_serial_generic_submit_read_urbs(port, GFP_KERNEL);
488 usb_serial_generic_submit_read_urbs(port, GFP_KERNEL);
489} 495}
490EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle); 496EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle);
491 497