hc
2023-11-06 e3e12f52b214121840b44c91de5b3e5af5d3eb84
kernel/drivers/usb/gadget/function/u_serial.c
....@@ -102,7 +102,6 @@
102102
103103 struct gserial *port_usb;
104104
105
- bool openclose; /* open/close in progress */
106105 u8 port_num;
107106
108107 struct list_head read_pool;
....@@ -595,81 +594,44 @@
595594 {
596595 int port_num = tty->index;
597596 struct gs_port *port;
598
- int status;
597
+ int status = 0;
599598
600
- do {
601
- mutex_lock(&ports[port_num].lock);
602
- port = ports[port_num].port;
603
- if (!port)
604
- status = -ENODEV;
605
- else {
606
- spin_lock_irq(&port->port_lock);
599
+ mutex_lock(&ports[port_num].lock);
600
+ port = ports[port_num].port;
601
+ if (!port) {
602
+ status = -ENODEV;
603
+ goto out;
604
+ }
607605
608
- /* already open? Great. */
609
- if (port->port.count) {
610
- status = 0;
611
- port->port.count++;
612
-
613
- /* currently opening/closing? wait ... */
614
- } else if (port->openclose) {
615
- status = -EBUSY;
616
-
617
- /* ... else we do the work */
618
- } else {
619
- status = -EAGAIN;
620
- port->openclose = true;
621
- }
622
- spin_unlock_irq(&port->port_lock);
623
- }
624
- mutex_unlock(&ports[port_num].lock);
625
-
626
- switch (status) {
627
- default:
628
- /* fully handled */
629
- return status;
630
- case -EAGAIN:
631
- /* must do the work */
632
- break;
633
- case -EBUSY:
634
- /* wait for EAGAIN task to finish */
635
- msleep(1);
636
- /* REVISIT could have a waitchannel here, if
637
- * concurrent open performance is important
638
- */
639
- break;
640
- }
641
- } while (status != -EAGAIN);
642
-
643
- /* Do the "real open" */
644606 spin_lock_irq(&port->port_lock);
645607
646608 /* allocate circular buffer on first open */
647609 if (!kfifo_initialized(&port->port_write_buf)) {
648610
649611 spin_unlock_irq(&port->port_lock);
612
+
613
+ /*
614
+ * portmaster's mutex still protects from simultaneous open(),
615
+ * and close() can't happen, yet.
616
+ */
617
+
650618 status = kfifo_alloc(&port->port_write_buf,
651619 WRITE_BUF_SIZE, GFP_KERNEL);
652
- spin_lock_irq(&port->port_lock);
653
-
654620 if (status) {
655621 pr_debug("gs_open: ttyGS%d (%p,%p) no buffer\n",
656
- port->port_num, tty, file);
657
- port->openclose = false;
658
- goto exit_unlock_port;
622
+ port_num, tty, file);
623
+ goto out;
659624 }
625
+
626
+ spin_lock_irq(&port->port_lock);
660627 }
661628
662
- /* REVISIT if REMOVED (ports[].port NULL), abort the open
663
- * to let rmmod work faster (but this way isn't wrong).
664
- */
665
-
666
- /* REVISIT maybe wait for "carrier detect" */
629
+ /* already open? Great. */
630
+ if (port->port.count++)
631
+ goto exit_unlock_port;
667632
668633 tty->driver_data = port;
669634 port->port.tty = tty;
670
-
671
- port->port.count = 1;
672
- port->openclose = false;
673635
674636 /* if connected, start the I/O stream */
675637 if (port->port_usb) {
....@@ -684,20 +646,21 @@
684646
685647 pr_debug("gs_open: ttyGS%d (%p,%p)\n", port->port_num, tty, file);
686648
687
- status = 0;
688
-
689649 exit_unlock_port:
690650 spin_unlock_irq(&port->port_lock);
651
+out:
652
+ mutex_unlock(&ports[port_num].lock);
691653 return status;
692654 }
693655
694
-static int gs_writes_finished(struct gs_port *p)
656
+static int gs_close_flush_done(struct gs_port *p)
695657 {
696658 int cond;
697659
698
- /* return true on disconnect or empty buffer */
660
+ /* return true on disconnect or empty buffer or if raced with open() */
699661 spin_lock_irq(&p->port_lock);
700
- cond = (p->port_usb == NULL) || !kfifo_len(&p->port_write_buf);
662
+ cond = p->port_usb == NULL || !kfifo_len(&p->port_write_buf) ||
663
+ p->port.count > 1;
701664 spin_unlock_irq(&p->port_lock);
702665
703666 return cond;
....@@ -711,6 +674,7 @@
711674 spin_lock_irq(&port->port_lock);
712675
713676 if (port->port.count != 1) {
677
+raced_with_open:
714678 if (port->port.count == 0)
715679 WARN_ON(1);
716680 else
....@@ -719,12 +683,6 @@
719683 }
720684
721685 pr_debug("gs_close: ttyGS%d (%p,%p) ...\n", port->port_num, tty, file);
722
-
723
- /* mark port as closing but in use; we can drop port lock
724
- * and sleep if necessary
725
- */
726
- port->openclose = true;
727
- port->port.count = 0;
728686
729687 gser = port->port_usb;
730688 if (gser && gser->disconnect)
....@@ -736,9 +694,13 @@
736694 if (kfifo_len(&port->port_write_buf) > 0 && gser) {
737695 spin_unlock_irq(&port->port_lock);
738696 wait_event_interruptible_timeout(port->drain_wait,
739
- gs_writes_finished(port),
697
+ gs_close_flush_done(port),
740698 GS_CLOSE_TIMEOUT * HZ);
741699 spin_lock_irq(&port->port_lock);
700
+
701
+ if (port->port.count != 1)
702
+ goto raced_with_open;
703
+
742704 gser = port->port_usb;
743705 }
744706
....@@ -751,9 +713,8 @@
751713 else
752714 kfifo_reset(&port->port_write_buf);
753715
716
+ port->port.count = 0;
754717 port->port.tty = NULL;
755
-
756
- port->openclose = false;
757718
758719 pr_debug("gs_close: ttyGS%d (%p,%p) done!\n",
759720 port->port_num, tty, file);
....@@ -1181,8 +1142,9 @@
11811142 int cond;
11821143
11831144 spin_lock_irq(&port->port_lock);
1184
- cond = (port->port.count == 0) && !port->openclose;
1145
+ cond = port->port.count == 0;
11851146 spin_unlock_irq(&port->port_lock);
1147
+
11861148 return cond;
11871149 }
11881150
....@@ -1375,7 +1337,7 @@
13751337
13761338 port->port_usb = NULL;
13771339 gser->ioport = NULL;
1378
- if (port->port.count > 0 || port->openclose) {
1340
+ if (port->port.count > 0) {
13791341 wake_up_interruptible(&port->drain_wait);
13801342 if (port->port.tty)
13811343 tty_hangup(port->port.tty);
....@@ -1388,7 +1350,7 @@
13881350
13891351 /* finally, free any unused/unusable I/O buffers */
13901352 spin_lock_irqsave(&port->port_lock, flags);
1391
- if (port->port.count == 0 && !port->openclose)
1353
+ if (port->port.count == 0)
13921354 kfifo_free(&port->port_write_buf);
13931355 gs_free_requests(gser->out, &port->read_pool, NULL);
13941356 gs_free_requests(gser->out, &port->read_queue, NULL);