.. | .. |
---|
81 | 81 | #define WRITE_BUF_SIZE 8192 /* TX only */ |
---|
82 | 82 | #define GS_CONSOLE_BUF_SIZE 8192 |
---|
83 | 83 | |
---|
| 84 | +/* Prevents race conditions while accessing gser->ioport */ |
---|
| 85 | +static DEFINE_SPINLOCK(serial_port_lock); |
---|
| 86 | + |
---|
84 | 87 | /* console info */ |
---|
85 | 88 | struct gs_console { |
---|
86 | 89 | struct console console; |
---|
.. | .. |
---|
912 | 915 | } |
---|
913 | 916 | |
---|
914 | 917 | req->length = size; |
---|
| 918 | + |
---|
| 919 | + spin_unlock_irq(&cons->lock); |
---|
915 | 920 | if (usb_ep_queue(ep, req, GFP_ATOMIC)) |
---|
916 | 921 | req->length = 0; |
---|
| 922 | + spin_lock_irq(&cons->lock); |
---|
917 | 923 | } |
---|
918 | 924 | |
---|
919 | 925 | static void gs_console_work(struct work_struct *work) |
---|
.. | .. |
---|
1374 | 1380 | if (!port) |
---|
1375 | 1381 | return; |
---|
1376 | 1382 | |
---|
| 1383 | + spin_lock_irqsave(&serial_port_lock, flags); |
---|
| 1384 | + |
---|
1377 | 1385 | /* 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); |
---|
1379 | 1387 | |
---|
1380 | 1388 | gs_console_disconnect(port); |
---|
1381 | 1389 | |
---|
.. | .. |
---|
1390 | 1398 | tty_hangup(port->port.tty); |
---|
1391 | 1399 | } |
---|
1392 | 1400 | 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); |
---|
1394 | 1403 | |
---|
1395 | 1404 | /* disable endpoints, aborting down any active I/O */ |
---|
1396 | 1405 | usb_ep_disable(gser->out); |
---|
.. | .. |
---|
1413 | 1422 | |
---|
1414 | 1423 | void gserial_suspend(struct gserial *gser) |
---|
1415 | 1424 | { |
---|
1416 | | - struct gs_port *port = gser->ioport; |
---|
| 1425 | + struct gs_port *port; |
---|
1417 | 1426 | unsigned long flags; |
---|
1418 | 1427 | |
---|
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); |
---|
1420 | 1438 | port->suspended = true; |
---|
1421 | 1439 | spin_unlock_irqrestore(&port->port_lock, flags); |
---|
1422 | 1440 | } |
---|
.. | .. |
---|
1424 | 1442 | |
---|
1425 | 1443 | void gserial_resume(struct gserial *gser) |
---|
1426 | 1444 | { |
---|
1427 | | - struct gs_port *port = gser->ioport; |
---|
| 1445 | + struct gs_port *port; |
---|
1428 | 1446 | unsigned long flags; |
---|
1429 | 1447 | |
---|
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); |
---|
1431 | 1458 | port->suspended = false; |
---|
1432 | 1459 | if (!port->start_delayed) { |
---|
1433 | 1460 | spin_unlock_irqrestore(&port->port_lock, flags); |
---|