提交 40a215fb 编写于 作者: L Linus Torvalds

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
......@@ -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 @@ static int n_tty_open(struct tty_struct *tty)
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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册