Skip to content

Commit

Permalink
Merge tag 'tty-4.16-rc6' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/gregkh/tty

Pull tty/serial driver fixes from Greg KH:
 "Here are some small tty core and serial driver fixes for 4.16-rc6.

  They resolve some newly reported bugs, as well as some very old ones,
  which is always nice to see. There is also a new device id added in
  here for good measure.

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'tty-4.16-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  serial: imx: fix bogus dev_err
  serial: sh-sci: prevent lockup on full TTY buffers
  serial: 8250_pci: Add Brainboxes UC-260 4 port serial device
  earlycon: add reg-offset to physical address before mapping
  serial: core: mark port as initialized in autoconfig
  serial: 8250_pci: Don't fail on multiport card class
  tty/serial: atmel: add new version check for usart
  tty: make n_tty_read() always abort if hangup is in progress
  • Loading branch information
Linus Torvalds committed Mar 14, 2018
2 parents 5e15d39 + 5d7f77e commit 6560ca4
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 5 deletions.
6 changes: 6 additions & 0 deletions drivers/tty/n_tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -2180,6 +2180,12 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
}
if (tty_hung_up_p(file))
break;
/*
* Abort readers for ttys which never actually
* get hung up. See __tty_hangup().
*/
if (test_bit(TTY_HUPPING, &tty->flags))
break;
if (!timeout)
break;
if (file->f_flags & O_NONBLOCK) {
Expand Down
21 changes: 18 additions & 3 deletions drivers/tty/serial/8250/8250_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -3387,11 +3387,9 @@ static int serial_pci_is_class_communication(struct pci_dev *dev)
/*
* If it is not a communications device or the programming
* interface is greater than 6, give up.
*
* (Should we try to make guesses for multiport serial devices
* later?)
*/
if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) &&
((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MULTISERIAL) &&
((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) ||
(dev->class & 0xff) > 6)
return -ENODEV;
Expand Down Expand Up @@ -3428,6 +3426,12 @@ serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
{
int num_iomem, num_port, first_port = -1, i;

/*
* Should we try to make guesses for multiport serial devices later?
*/
if ((dev->class >> 8) == PCI_CLASS_COMMUNICATION_MULTISERIAL)
return -ENODEV;

num_iomem = num_port = 0;
for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
Expand Down Expand Up @@ -4698,6 +4702,17 @@ static const struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS400,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0dc0 */
pbn_b2_4_115200 },
/*
* BrainBoxes UC-260
*/
{ PCI_VENDOR_ID_INTASHIELD, 0x0D21,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00,
pbn_b2_4_115200 },
{ PCI_VENDOR_ID_INTASHIELD, 0x0E34,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00,
pbn_b2_4_115200 },
/*
* Perle PCI-RAS cards
*/
Expand Down
1 change: 1 addition & 0 deletions drivers/tty/serial/atmel_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -1734,6 +1734,7 @@ static void atmel_get_ip_name(struct uart_port *port)
switch (version) {
case 0x302:
case 0x10213:
case 0x10302:
dev_dbg(port->dev, "This version is usart\n");
atmel_port->has_frac_baudrate = true;
atmel_port->has_hw_timer = true;
Expand Down
3 changes: 2 additions & 1 deletion drivers/tty/serial/earlycon.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,11 +245,12 @@ int __init of_setup_earlycon(const struct earlycon_id *match,
}
port->mapbase = addr;
port->uartclk = BASE_BAUD * 16;
port->membase = earlycon_map(port->mapbase, SZ_4K);

val = of_get_flat_dt_prop(node, "reg-offset", NULL);
if (val)
port->mapbase += be32_to_cpu(*val);
port->membase = earlycon_map(port->mapbase, SZ_4K);

val = of_get_flat_dt_prop(node, "reg-shift", NULL);
if (val)
port->regshift = be32_to_cpu(*val);
Expand Down
2 changes: 1 addition & 1 deletion drivers/tty/serial/imx.c
Original file line number Diff line number Diff line change
Expand Up @@ -2093,7 +2093,7 @@ static int serial_imx_probe(struct platform_device *pdev)
uart_get_rs485_mode(&pdev->dev, &sport->port.rs485);

if (sport->port.rs485.flags & SER_RS485_ENABLED &&
(!sport->have_rtscts || !sport->have_rtsgpio))
(!sport->have_rtscts && !sport->have_rtsgpio))
dev_err(&pdev->dev, "no RTS control, disabling rs485\n");

imx_rs485_config(&sport->port, &sport->port.rs485);
Expand Down
2 changes: 2 additions & 0 deletions drivers/tty/serial/serial_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,8 @@ static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state)
uport->ops->config_port(uport, flags);

ret = uart_startup(tty, state, 1);
if (ret == 0)
tty_port_set_initialized(port, true);
if (ret > 0)
ret = 0;
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/tty/serial/sh-sci.c
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,8 @@ static void sci_receive_chars(struct uart_port *port)
/* Tell the rest of the system the news. New characters! */
tty_flip_buffer_push(tport);
} else {
/* TTY buffers full; read from RX reg to prevent lockup */
serial_port_in(port, SCxRDR);
serial_port_in(port, SCxSR); /* dummy read */
sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
}
Expand Down
9 changes: 9 additions & 0 deletions drivers/tty/tty_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,14 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session)
return;
}

/*
* Some console devices aren't actually hung up for technical and
* historical reasons, which can lead to indefinite interruptible
* sleep in n_tty_read(). The following explicitly tells
* n_tty_read() to abort readers.
*/
set_bit(TTY_HUPPING, &tty->flags);

/* inuse_filps is protected by the single tty lock,
this really needs to change if we want to flush the
workqueue with the lock held */
Expand Down Expand Up @@ -640,6 +648,7 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session)
* from the ldisc side, which is now guaranteed.
*/
set_bit(TTY_HUPPED, &tty->flags);
clear_bit(TTY_HUPPING, &tty->flags);
tty_unlock(tty);

if (f)
Expand Down
1 change: 1 addition & 0 deletions include/linux/tty.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ struct tty_file_private {
#define TTY_PTY_LOCK 16 /* pty private */
#define TTY_NO_WRITE_SPLIT 17 /* Preserve write boundaries to driver */
#define TTY_HUPPED 18 /* Post driver->hangup() */
#define TTY_HUPPING 19 /* Hangup in progress */
#define TTY_LDISC_HALTED 22 /* Line discipline is halted */

/* Values for tty->flow_change */
Expand Down

0 comments on commit 6560ca4

Please sign in to comment.