TTY/Serial driver fixes for 3.14-rc3
Here are a small number of tty/serial driver fixes to resolve reported issues with 3.14-rc and earlier (in the case of the vt bugfix.) Some of these have been tested and reported by a number of people as the tty bugfix was pretty commonly hit on some platforms. All have been in linux-next for a while. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iEYEABECAAYFAlL+iJAACgkQMUfUDdst+ynLeACfcDynM0/zoSAvfscALTpF796A KU8AnRyiac0BauTLDmryJSr6pJqkAzMM =6iYo -----END PGP SIGNATURE----- Merge tag 'tty-3.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty Pull tty/serial driver fixes from Greg KH: "Here are a small number of tty/serial driver fixes to resolve reported issues with 3.14-rc and earlier (in the case of the vt bugfix). Some of these have been tested and reported by a number of people as the tty bugfix was pretty commonly hit on some platforms. All have been in linux-next for a while" * tag 'tty-3.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: vt: Fix secure clear screen serial: 8250: Support XR17V35x fraction divisor n_tty: Fix stale echo output serial: sirf: fix kernel panic caused by unpaired spinlock serial: 8250_pci: unbreak last serial ports on NetMos 9865 cards n_tty: Fix poll() when TIME_CHAR and MIN_CHAR == 0 serial: omap: fix rs485 probe on defered pinctrl serial: 8250_dw: fix compilation warning when !CONFIG_PM_SLEEP serial: omap-serial: Move info message to probe function tty: Set correct tty name in 'active' sysfs attribute tty: n_gsm: Fix for modems with brk in modem status control drivers/tty/hvc: don't use module_init in non-modular hyp. console code
This commit is contained in:
Коммит
40a215fba1
|
@ -3,7 +3,8 @@ Date: Nov 2010
|
|||
Contact: Kay Sievers <kay.sievers@vrfy.org>
|
||||
Description:
|
||||
Shows the list of currently configured
|
||||
console devices, like 'tty1 ttyS0'.
|
||||
tty devices used for the console,
|
||||
like 'tty1 ttyS0'.
|
||||
The last entry in the file is the active
|
||||
device connected to /dev/console.
|
||||
The file supports poll() to detect virtual
|
||||
|
|
|
@ -255,13 +255,7 @@ static int __init hvc_opal_init(void)
|
|||
/* Register as a vio device to receive callbacks */
|
||||
return platform_driver_register(&hvc_opal_driver);
|
||||
}
|
||||
module_init(hvc_opal_init);
|
||||
|
||||
static void __exit hvc_opal_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&hvc_opal_driver);
|
||||
}
|
||||
module_exit(hvc_opal_exit);
|
||||
device_initcall(hvc_opal_init);
|
||||
|
||||
static void udbg_opal_putc(char c)
|
||||
{
|
||||
|
|
|
@ -102,17 +102,7 @@ static int __init hvc_rtas_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
module_init(hvc_rtas_init);
|
||||
|
||||
/* This will tear down the tty portion of the driver */
|
||||
static void __exit hvc_rtas_exit(void)
|
||||
{
|
||||
/* Really the fun isn't over until the worker thread breaks down and
|
||||
* the tty cleans up */
|
||||
if (hvc_rtas_dev)
|
||||
hvc_remove(hvc_rtas_dev);
|
||||
}
|
||||
module_exit(hvc_rtas_exit);
|
||||
device_initcall(hvc_rtas_init);
|
||||
|
||||
/* This will happen prior to module init. There is no tty at this time? */
|
||||
static int __init hvc_rtas_console_init(void)
|
||||
|
|
|
@ -80,14 +80,7 @@ static int __init hvc_udbg_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
module_init(hvc_udbg_init);
|
||||
|
||||
static void __exit hvc_udbg_exit(void)
|
||||
{
|
||||
if (hvc_udbg_dev)
|
||||
hvc_remove(hvc_udbg_dev);
|
||||
}
|
||||
module_exit(hvc_udbg_exit);
|
||||
device_initcall(hvc_udbg_init);
|
||||
|
||||
static int __init hvc_udbg_console_init(void)
|
||||
{
|
||||
|
|
|
@ -561,18 +561,7 @@ static int __init xen_hvc_init(void)
|
|||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
static void __exit xen_hvc_fini(void)
|
||||
{
|
||||
struct xencons_info *entry, *next;
|
||||
|
||||
if (list_empty(&xenconsoles))
|
||||
return;
|
||||
|
||||
list_for_each_entry_safe(entry, next, &xenconsoles, list) {
|
||||
xen_console_remove(entry);
|
||||
}
|
||||
}
|
||||
device_initcall(xen_hvc_init);
|
||||
|
||||
static int xen_cons_init(void)
|
||||
{
|
||||
|
@ -598,10 +587,6 @@ static int xen_cons_init(void)
|
|||
hvc_instantiate(HVC_COOKIE, 0, ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
module_init(xen_hvc_init);
|
||||
module_exit(xen_hvc_fini);
|
||||
console_initcall(xen_cons_init);
|
||||
|
||||
#ifdef CONFIG_EARLY_PRINTK
|
||||
|
|
|
@ -1090,6 +1090,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen)
|
|||
{
|
||||
unsigned int addr = 0;
|
||||
unsigned int modem = 0;
|
||||
unsigned int brk = 0;
|
||||
struct gsm_dlci *dlci;
|
||||
int len = clen;
|
||||
u8 *dp = data;
|
||||
|
@ -1116,6 +1117,16 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen)
|
|||
if (len == 0)
|
||||
return;
|
||||
}
|
||||
len--;
|
||||
if (len > 0) {
|
||||
while (gsm_read_ea(&brk, *dp++) == 0) {
|
||||
len--;
|
||||
if (len == 0)
|
||||
return;
|
||||
}
|
||||
modem <<= 7;
|
||||
modem |= (brk & 0x7f);
|
||||
}
|
||||
tty = tty_port_tty_get(&dlci->port);
|
||||
gsm_process_modem(tty, dlci, modem, clen);
|
||||
if (tty) {
|
||||
|
|
|
@ -817,8 +817,7 @@ static void process_echoes(struct tty_struct *tty)
|
|||
struct n_tty_data *ldata = tty->disc_data;
|
||||
size_t echoed;
|
||||
|
||||
if ((!L_ECHO(tty) && !L_ECHONL(tty)) ||
|
||||
ldata->echo_mark == ldata->echo_tail)
|
||||
if (ldata->echo_mark == ldata->echo_tail)
|
||||
return;
|
||||
|
||||
mutex_lock(&ldata->output_lock);
|
||||
|
@ -1244,7 +1243,8 @@ n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c)
|
|||
if (L_ECHO(tty)) {
|
||||
echo_char(c, tty);
|
||||
commit_echoes(tty);
|
||||
}
|
||||
} else
|
||||
process_echoes(tty);
|
||||
isig(signal, tty);
|
||||
return;
|
||||
}
|
||||
|
@ -1274,7 +1274,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
|
|||
if (I_IXON(tty)) {
|
||||
if (c == START_CHAR(tty)) {
|
||||
start_tty(tty);
|
||||
commit_echoes(tty);
|
||||
process_echoes(tty);
|
||||
return 0;
|
||||
}
|
||||
if (c == STOP_CHAR(tty)) {
|
||||
|
@ -1820,8 +1820,10 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
|
|||
* Fix tty hang when I_IXON(tty) is cleared, but the tty
|
||||
* been stopped by STOP_CHAR(tty) before it.
|
||||
*/
|
||||
if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped)
|
||||
if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) {
|
||||
start_tty(tty);
|
||||
process_echoes(tty);
|
||||
}
|
||||
|
||||
/* The termios change make the tty ready for I/O */
|
||||
if (waitqueue_active(&tty->write_wait))
|
||||
|
@ -1896,7 +1898,7 @@ err:
|
|||
static inline int input_available_p(struct tty_struct *tty, int poll)
|
||||
{
|
||||
struct n_tty_data *ldata = tty->disc_data;
|
||||
int amt = poll && !TIME_CHAR(tty) ? MIN_CHAR(tty) : 1;
|
||||
int amt = poll && !TIME_CHAR(tty) && MIN_CHAR(tty) ? MIN_CHAR(tty) : 1;
|
||||
|
||||
if (ldata->icanon && !L_EXTPROC(tty)) {
|
||||
if (ldata->canon_head != ldata->read_tail)
|
||||
|
|
|
@ -2432,6 +2432,24 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
|
||||
serial_dl_write(up, quot);
|
||||
|
||||
/*
|
||||
* XR17V35x UARTs have an extra fractional divisor register (DLD)
|
||||
*
|
||||
* We need to recalculate all of the registers, because DLM and DLL
|
||||
* are already rounded to a whole integer.
|
||||
*
|
||||
* When recalculating we use a 32x clock instead of a 16x clock to
|
||||
* allow 1-bit for rounding in the fractional part.
|
||||
*/
|
||||
if (up->port.type == PORT_XR17V35X) {
|
||||
unsigned int baud_x32 = (port->uartclk * 2) / baud;
|
||||
u16 quot = baud_x32 / 32;
|
||||
u8 quot_frac = DIV_ROUND_CLOSEST(baud_x32 % 32, 2);
|
||||
|
||||
serial_dl_write(up, quot);
|
||||
serial_port_out(port, 0x2, quot_frac & 0xf);
|
||||
}
|
||||
|
||||
/*
|
||||
* LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
|
||||
* is written without DLAB set, this mode will be disabled.
|
||||
|
|
|
@ -391,7 +391,7 @@ static int dw8250_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int dw8250_suspend(struct device *dev)
|
||||
{
|
||||
struct dw8250_data *data = dev_get_drvdata(dev);
|
||||
|
@ -409,7 +409,7 @@ static int dw8250_resume(struct device *dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
static int dw8250_runtime_suspend(struct device *dev)
|
||||
|
|
|
@ -783,7 +783,8 @@ static int pci_netmos_9900_setup(struct serial_private *priv,
|
|||
{
|
||||
unsigned int bar;
|
||||
|
||||
if ((priv->dev->subsystem_device & 0xff00) == 0x3000) {
|
||||
if ((priv->dev->device != PCI_DEVICE_ID_NETMOS_9865) &&
|
||||
(priv->dev->subsystem_device & 0xff00) == 0x3000) {
|
||||
/* netmos apparently orders BARs by datasheet layout, so serial
|
||||
* ports get BARs 0 and 3 (or 1 and 4 for memmapped)
|
||||
*/
|
||||
|
|
|
@ -738,9 +738,6 @@ static int serial_omap_startup(struct uart_port *port)
|
|||
return retval;
|
||||
}
|
||||
disable_irq(up->wakeirq);
|
||||
} else {
|
||||
dev_info(up->port.dev, "no wakeirq for uart%d\n",
|
||||
up->port.line);
|
||||
}
|
||||
|
||||
dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->port.line);
|
||||
|
@ -1604,8 +1601,11 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up,
|
|||
flags & SER_RS485_RTS_AFTER_SEND);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else
|
||||
} else if (up->rts_gpio == -EPROBE_DEFER) {
|
||||
return -EPROBE_DEFER;
|
||||
} else {
|
||||
up->rts_gpio = -EINVAL;
|
||||
}
|
||||
|
||||
if (of_property_read_u32_array(np, "rs485-rts-delay",
|
||||
rs485_delay, 2) == 0) {
|
||||
|
@ -1687,6 +1687,9 @@ static int serial_omap_probe(struct platform_device *pdev)
|
|||
up->port.iotype = UPIO_MEM;
|
||||
up->port.irq = uartirq;
|
||||
up->wakeirq = wakeirq;
|
||||
if (!up->wakeirq)
|
||||
dev_info(up->port.dev, "no wakeirq for uart%d\n",
|
||||
up->port.line);
|
||||
|
||||
up->port.regshift = 2;
|
||||
up->port.fifosize = 64;
|
||||
|
|
|
@ -542,8 +542,10 @@ static void sirfsoc_rx_tmo_process_tl(unsigned long param)
|
|||
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
|
||||
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
|
||||
SIRFUART_IO_MODE);
|
||||
sirfsoc_uart_pio_rx_chars(port, 4 - sirfport->rx_io_count);
|
||||
spin_unlock_irqrestore(&sirfport->rx_lock, flags);
|
||||
spin_lock(&port->lock);
|
||||
sirfsoc_uart_pio_rx_chars(port, 4 - sirfport->rx_io_count);
|
||||
spin_unlock(&port->lock);
|
||||
if (sirfport->rx_io_count == 4) {
|
||||
spin_lock_irqsave(&sirfport->rx_lock, flags);
|
||||
sirfport->rx_io_count = 0;
|
||||
|
|
|
@ -1267,16 +1267,17 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p)
|
|||
* @p: output buffer of at least 7 bytes
|
||||
*
|
||||
* Generate a name from a driver reference and write it to the output
|
||||
* buffer.
|
||||
* buffer. Return the number of bytes written.
|
||||
*
|
||||
* Locking: None
|
||||
*/
|
||||
static void tty_line_name(struct tty_driver *driver, int index, char *p)
|
||||
static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p)
|
||||
{
|
||||
if (driver->flags & TTY_DRIVER_UNNUMBERED_NODE)
|
||||
strcpy(p, driver->name);
|
||||
return sprintf(p, "%s", driver->name);
|
||||
else
|
||||
sprintf(p, "%s%d", driver->name, index + driver->name_base);
|
||||
return sprintf(p, "%s%d", driver->name,
|
||||
index + driver->name_base);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3545,9 +3546,19 @@ static ssize_t show_cons_active(struct device *dev,
|
|||
if (i >= ARRAY_SIZE(cs))
|
||||
break;
|
||||
}
|
||||
while (i--)
|
||||
count += sprintf(buf + count, "%s%d%c",
|
||||
cs[i]->name, cs[i]->index, i ? ' ':'\n');
|
||||
while (i--) {
|
||||
struct tty_driver *driver;
|
||||
const char *name = cs[i]->name;
|
||||
int index = cs[i]->index;
|
||||
|
||||
driver = cs[i]->device(cs[i], &index);
|
||||
if (driver) {
|
||||
count += tty_line_name(driver, index, buf + count);
|
||||
count += sprintf(buf + count, "%c", i ? ' ':'\n');
|
||||
} else
|
||||
count += sprintf(buf + count, "%s%d%c",
|
||||
name, index, i ? ' ':'\n');
|
||||
}
|
||||
console_unlock();
|
||||
|
||||
return count;
|
||||
|
|
|
@ -1164,6 +1164,8 @@ static void csi_J(struct vc_data *vc, int vpar)
|
|||
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
|
||||
vc->vc_screenbuf_size >> 1);
|
||||
set_origin(vc);
|
||||
if (CON_IS_VISIBLE(vc))
|
||||
update_screen(vc);
|
||||
/* fall through */
|
||||
case 2: /* erase whole display */
|
||||
count = vc->vc_cols * vc->vc_rows;
|
||||
|
|
Загрузка…
Ссылка в новой задаче