hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/usb/gadget/function/u_serial.c
....@@ -81,6 +81,9 @@
8181 #define WRITE_BUF_SIZE 8192 /* TX only */
8282 #define GS_CONSOLE_BUF_SIZE 8192
8383
84
+/* Prevents race conditions while accessing gser->ioport */
85
+static DEFINE_SPINLOCK(serial_port_lock);
86
+
8487 /* console info */
8588 struct gs_console {
8689 struct console console;
....@@ -912,8 +915,11 @@
912915 }
913916
914917 req->length = size;
918
+
919
+ spin_unlock_irq(&cons->lock);
915920 if (usb_ep_queue(ep, req, GFP_ATOMIC))
916921 req->length = 0;
922
+ spin_lock_irq(&cons->lock);
917923 }
918924
919925 static void gs_console_work(struct work_struct *work)
....@@ -1374,8 +1380,10 @@
13741380 if (!port)
13751381 return;
13761382
1383
+ spin_lock_irqsave(&serial_port_lock, flags);
1384
+
13771385 /* tell the TTY glue not to do I/O here any more */
1378
- spin_lock_irqsave(&port->port_lock, flags);
1386
+ spin_lock(&port->port_lock);
13791387
13801388 gs_console_disconnect(port);
13811389
....@@ -1390,7 +1398,8 @@
13901398 tty_hangup(port->port.tty);
13911399 }
13921400 port->suspended = false;
1393
- spin_unlock_irqrestore(&port->port_lock, flags);
1401
+ spin_unlock(&port->port_lock);
1402
+ spin_unlock_irqrestore(&serial_port_lock, flags);
13941403
13951404 /* disable endpoints, aborting down any active I/O */
13961405 usb_ep_disable(gser->out);
....@@ -1413,10 +1422,19 @@
14131422
14141423 void gserial_suspend(struct gserial *gser)
14151424 {
1416
- struct gs_port *port = gser->ioport;
1425
+ struct gs_port *port;
14171426 unsigned long flags;
14181427
1419
- spin_lock_irqsave(&port->port_lock, flags);
1428
+ spin_lock_irqsave(&serial_port_lock, flags);
1429
+ port = gser->ioport;
1430
+
1431
+ if (!port) {
1432
+ spin_unlock_irqrestore(&serial_port_lock, flags);
1433
+ return;
1434
+ }
1435
+
1436
+ spin_lock(&port->port_lock);
1437
+ spin_unlock(&serial_port_lock);
14201438 port->suspended = true;
14211439 spin_unlock_irqrestore(&port->port_lock, flags);
14221440 }
....@@ -1424,10 +1442,19 @@
14241442
14251443 void gserial_resume(struct gserial *gser)
14261444 {
1427
- struct gs_port *port = gser->ioport;
1445
+ struct gs_port *port;
14281446 unsigned long flags;
14291447
1430
- spin_lock_irqsave(&port->port_lock, flags);
1448
+ spin_lock_irqsave(&serial_port_lock, flags);
1449
+ port = gser->ioport;
1450
+
1451
+ if (!port) {
1452
+ spin_unlock_irqrestore(&serial_port_lock, flags);
1453
+ return;
1454
+ }
1455
+
1456
+ spin_lock(&port->port_lock);
1457
+ spin_unlock(&serial_port_lock);
14311458 port->suspended = false;
14321459 if (!port->start_delayed) {
14331460 spin_unlock_irqrestore(&port->port_lock, flags);