Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'tty-3.15-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty/serial fixes from Greg KH:
"Here are a few tty/serial fixes for 3.15-rc3 that resolve a number of
reported issues in the 8250 and samsung serial drivers, as well as a
character loss fix for the tty core that was caused by the lock
removal patches a release ago"

* tag 'tty-3.15-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
serial_core: fix uart PORT_UNKNOWN handling
serial: samsung: Change barrier() to cpu_relax() in console output
serial: samsung: don't check config for every character
serial: samsung: Use the passed in "port", fixing kgdb w/ no console
serial: 8250: Fix thread unsafe __dma_tx_complete function
8250_core: Fix unwanted TX chars write
tty: Fix race condition between __tty_buffer_request_room and flush_to_ldisc

+56 -34
+1 -1
drivers/tty/serial/8250/8250_core.c
··· 1520 1520 status = serial8250_rx_chars(up, status); 1521 1521 } 1522 1522 serial8250_modem_status(up); 1523 - if (status & UART_LSR_THRE) 1523 + if (!up->dma && (status & UART_LSR_THRE)) 1524 1524 serial8250_tx_chars(up); 1525 1525 1526 1526 spin_unlock_irqrestore(&port->lock, flags);
+7 -2
drivers/tty/serial/8250/8250_dma.c
··· 20 20 struct uart_8250_port *p = param; 21 21 struct uart_8250_dma *dma = p->dma; 22 22 struct circ_buf *xmit = &p->port.state->xmit; 23 - 24 - dma->tx_running = 0; 23 + unsigned long flags; 25 24 26 25 dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr, 27 26 UART_XMIT_SIZE, DMA_TO_DEVICE); 27 + 28 + spin_lock_irqsave(&p->port.lock, flags); 29 + 30 + dma->tx_running = 0; 28 31 29 32 xmit->tail += dma->tx_size; 30 33 xmit->tail &= UART_XMIT_SIZE - 1; ··· 38 35 39 36 if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) 40 37 serial8250_tx_dma(p); 38 + 39 + spin_unlock_irqrestore(&p->port.lock, flags); 41 40 } 42 41 43 42 static void __dma_rx_complete(void *param)
+12 -11
drivers/tty/serial/samsung.c
··· 1446 1446 static void s3c24xx_serial_put_poll_char(struct uart_port *port, 1447 1447 unsigned char c) 1448 1448 { 1449 - unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); 1450 - unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON); 1449 + unsigned int ufcon = rd_regl(port, S3C2410_UFCON); 1450 + unsigned int ucon = rd_regl(port, S3C2410_UCON); 1451 1451 1452 1452 /* not possible to xmit on unconfigured port */ 1453 1453 if (!s3c24xx_port_configured(ucon)) ··· 1455 1455 1456 1456 while (!s3c24xx_serial_console_txrdy(port, ufcon)) 1457 1457 cpu_relax(); 1458 - wr_regb(cons_uart, S3C2410_UTXH, c); 1458 + wr_regb(port, S3C2410_UTXH, c); 1459 1459 } 1460 1460 1461 1461 #endif /* CONFIG_CONSOLE_POLL */ ··· 1463 1463 static void 1464 1464 s3c24xx_serial_console_putchar(struct uart_port *port, int ch) 1465 1465 { 1466 - unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); 1467 - unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON); 1468 - 1469 - /* not possible to xmit on unconfigured port */ 1470 - if (!s3c24xx_port_configured(ucon)) 1471 - return; 1466 + unsigned int ufcon = rd_regl(port, S3C2410_UFCON); 1472 1467 1473 1468 while (!s3c24xx_serial_console_txrdy(port, ufcon)) 1474 - barrier(); 1475 - wr_regb(cons_uart, S3C2410_UTXH, ch); 1469 + cpu_relax(); 1470 + wr_regb(port, S3C2410_UTXH, ch); 1476 1471 } 1477 1472 1478 1473 static void 1479 1474 s3c24xx_serial_console_write(struct console *co, const char *s, 1480 1475 unsigned int count) 1481 1476 { 1477 + unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON); 1478 + 1479 + /* not possible to xmit on unconfigured port */ 1480 + if (!s3c24xx_port_configured(ucon)) 1481 + return; 1482 + 1482 1483 uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar); 1483 1484 } 1484 1485
+21 -18
drivers/tty/serial/serial_core.c
··· 137 137 return 1; 138 138 139 139 /* 140 + * Make sure the device is in D0 state. 141 + */ 142 + uart_change_pm(state, UART_PM_STATE_ON); 143 + 144 + /* 140 145 * Initialise and allocate the transmit and temporary 141 146 * buffer. 142 147 */ ··· 830 825 * If we fail to request resources for the 831 826 * new port, try to restore the old settings. 832 827 */ 833 - if (retval && old_type != PORT_UNKNOWN) { 828 + if (retval) { 834 829 uport->iobase = old_iobase; 835 830 uport->type = old_type; 836 831 uport->hub6 = old_hub6; 837 832 uport->iotype = old_iotype; 838 833 uport->regshift = old_shift; 839 834 uport->mapbase = old_mapbase; 840 - retval = uport->ops->request_port(uport); 841 - /* 842 - * If we failed to restore the old settings, 843 - * we fail like this. 844 - */ 845 - if (retval) 846 - uport->type = PORT_UNKNOWN; 847 835 848 - /* 849 - * We failed anyway. 850 - */ 851 - retval = -EBUSY; 836 + if (old_type != PORT_UNKNOWN) { 837 + retval = uport->ops->request_port(uport); 838 + /* 839 + * If we failed to restore the old settings, 840 + * we fail like this. 841 + */ 842 + if (retval) 843 + uport->type = PORT_UNKNOWN; 844 + 845 + /* 846 + * We failed anyway. 847 + */ 848 + retval = -EBUSY; 849 + } 850 + 852 851 /* Added to return the correct error -Ram Gupta */ 853 852 goto exit; 854 853 } ··· 1578 1569 retval = -EAGAIN; 1579 1570 goto err_dec_count; 1580 1571 } 1581 - 1582 - /* 1583 - * Make sure the device is in D0 state. 1584 - */ 1585 - if (port->count == 1) 1586 - uart_change_pm(state, UART_PM_STATE_ON); 1587 1572 1588 1573 /* 1589 1574 * Start up the serial port.
+14 -2
drivers/tty/tty_buffer.c
··· 255 255 if (change || left < size) { 256 256 /* This is the slow path - looking for new buffers to use */ 257 257 if ((n = tty_buffer_alloc(port, size)) != NULL) { 258 + unsigned long iflags; 259 + 258 260 n->flags = flags; 259 261 buf->tail = n; 262 + 263 + spin_lock_irqsave(&buf->flush_lock, iflags); 260 264 b->commit = b->used; 261 - smp_mb(); 262 265 b->next = n; 266 + spin_unlock_irqrestore(&buf->flush_lock, iflags); 267 + 263 268 } else if (change) 264 269 size = 0; 265 270 else ··· 448 443 mutex_lock(&buf->lock); 449 444 450 445 while (1) { 446 + unsigned long flags; 451 447 struct tty_buffer *head = buf->head; 452 448 int count; 453 449 ··· 456 450 if (atomic_read(&buf->priority)) 457 451 break; 458 452 453 + spin_lock_irqsave(&buf->flush_lock, flags); 459 454 count = head->commit - head->read; 460 455 if (!count) { 461 - if (head->next == NULL) 456 + if (head->next == NULL) { 457 + spin_unlock_irqrestore(&buf->flush_lock, flags); 462 458 break; 459 + } 463 460 buf->head = head->next; 461 + spin_unlock_irqrestore(&buf->flush_lock, flags); 464 462 tty_buffer_free(port, head); 465 463 continue; 466 464 } 465 + spin_unlock_irqrestore(&buf->flush_lock, flags); 467 466 468 467 count = receive_buf(tty, head, count); 469 468 if (!count) ··· 523 512 struct tty_bufhead *buf = &port->buf; 524 513 525 514 mutex_init(&buf->lock); 515 + spin_lock_init(&buf->flush_lock); 526 516 tty_buffer_reset(&buf->sentinel, 0); 527 517 buf->head = &buf->sentinel; 528 518 buf->tail = &buf->sentinel;
+1
include/linux/tty.h
··· 61 61 struct tty_buffer *head; /* Queue head */ 62 62 struct work_struct work; 63 63 struct mutex lock; 64 + spinlock_t flush_lock; 64 65 atomic_t priority; 65 66 struct tty_buffer sentinel; 66 67 struct llist_head free; /* Free queue head */