summaryrefslogtreecommitdiff
path: root/drivers/tty
diff options
context:
space:
mode:
authorXinyu Chen <xinyu.chen@freescale.com>2012-07-25 16:54:33 +0800
committerXinyu Chen <xinyu.chen@freescale.com>2012-07-25 16:54:33 +0800
commit10ca2f12149b8c3fde9af51da89736529892dc69 (patch)
tree1a5118db41796df0a40c20467f37542e957e87a0 /drivers/tty
parent3fb99edfabe05a47803eba7f39109b5eb86e25df (diff)
parentcf3095062b75f6e518c6ef8a25b47a5b2ced7668 (diff)
Merge remote branch 'fsl-linux-sdk/imx_3.0.35' into imx_3.0.35_android
Conflicts: arch/arm/configs/imx6_defconfig arch/arm/configs/imx6_updater_defconfig arch/arm/configs/imx6s_defconfig arch/arm/include/asm/dma-mapping.h arch/arm/kernel/smp.c arch/arm/mach-mx6/Kconfig arch/arm/mach-mx6/board-mx6dl_arm2.h arch/arm/mach-mx6/board-mx6dl_sabresd.h arch/arm/mach-mx6/board-mx6q_arm2.c arch/arm/mach-mx6/board-mx6q_arm2.h arch/arm/mach-mx6/board-mx6q_sabreauto.c arch/arm/mach-mx6/board-mx6q_sabreauto.h arch/arm/mach-mx6/board-mx6q_sabrelite.c arch/arm/mach-mx6/board-mx6q_sabresd.c arch/arm/mach-mx6/board-mx6q_sabresd.h arch/arm/mach-mx6/board-mx6sl_arm2.c arch/arm/mach-mx6/board-mx6sl_arm2.h arch/arm/mach-mx6/board-mx6solo_sabreauto.h arch/arm/mach-mx6/bus_freq.c arch/arm/mach-mx6/clock.c arch/arm/mach-mx6/clock_mx6sl.c arch/arm/mach-mx6/cpu.c arch/arm/mach-mx6/crm_regs.h arch/arm/mach-mx6/devices-imx6q.h arch/arm/mach-mx6/devices.c arch/arm/mach-mx6/mx6_anatop_regulator.c arch/arm/mach-mx6/pcie.c arch/arm/mach-mx6/system.c arch/arm/mm/dma-mapping.c arch/arm/plat-mxc/devices/Makefile arch/arm/plat-mxc/devices/platform-imx-dcp.c arch/arm/plat-mxc/devices/platform-imx-ocotp.c arch/arm/plat-mxc/devices/platform-imx-rngb.c arch/arm/plat-mxc/devices/platform-mxc_hdmi.c arch/arm/plat-mxc/include/mach/devices-common.h arch/arm/plat-mxc/include/mach/esdhc.h arch/arm/plat-mxc/include/mach/iomux-mx6dl.h arch/arm/plat-mxc/include/mach/iomux-mx6q.h arch/arm/plat-mxc/include/mach/memory.h arch/arm/plat-mxc/include/mach/mx6.h arch/arm/plat-mxc/include/mach/mxc_edid.h arch/arm/plat-mxc/include/mach/mxc_hdmi.h arch/arm/plat-mxc/system.c drivers/Kconfig drivers/char/hw_random/fsl-rngc.c drivers/cpufreq/Makefile drivers/cpufreq/cpufreq_interactive.c drivers/crypto/Kconfig drivers/crypto/caam/caamalg.c drivers/crypto/caam/compat.h drivers/crypto/caam/ctrl.c drivers/crypto/caam/desc_constr.h drivers/crypto/caam/intern.h drivers/crypto/dcp.c drivers/dma/pch_dma.c drivers/input/keyboard/gpio_keys.c drivers/input/touchscreen/egalax_ts.c drivers/input/touchscreen/max11801_ts.c drivers/media/video/mxc/capture/Kconfig drivers/media/video/mxc/capture/adv7180.c drivers/media/video/mxc/capture/ipu_csi_enc.c drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c drivers/media/video/mxc/capture/mxc_v4l2_capture.c drivers/media/video/mxc/capture/ov5640_mipi.c drivers/media/video/mxc/output/mxc_vout.c drivers/misc/Kconfig drivers/misc/Makefile drivers/mmc/card/block.c drivers/mmc/core/mmc.c drivers/mmc/host/mmci.c drivers/mmc/host/sdhci-esdhc-imx.c drivers/mmc/host/sdhci.c drivers/mmc/host/sdhci.h drivers/mxc/Kconfig drivers/mxc/Makefile drivers/mxc/asrc/mxc_asrc.c drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c drivers/mxc/ipu3/ipu_device.c drivers/mxc/vpu/mxc_vpu.c drivers/net/fec.c drivers/net/wireless/Makefile drivers/power/sabresd_battery.c drivers/regulator/core.c drivers/tty/serial/imx.c drivers/usb/core/hub.c drivers/usb/gadget/arcotg_udc.c drivers/usb/gadget/fsl_updater.c drivers/usb/gadget/inode.c drivers/usb/host/ehci-hub.c drivers/video/mxc/ldb.c drivers/video/mxc/mipi_dsi.c drivers/video/mxc/mxc_dispdrv.c drivers/video/mxc/mxc_dispdrv.h drivers/video/mxc/mxc_edid.c drivers/video/mxc/mxc_elcdif_fb.c drivers/video/mxc/mxc_ipuv3_fb.c drivers/video/mxc/mxc_spdc_fb.c drivers/video/mxc_hdmi.c drivers/watchdog/imx2_wdt.c fs/proc/base.c include/linux/mmc/host.h include/linux/mmc/sdhci.h include/linux/mxc_v4l2.h kernel/power/main.c sound/soc/codecs/mxc_hdmi.c sound/soc/codecs/mxc_spdif.c sound/soc/codecs/wm8962.c sound/soc/imx/Kconfig sound/soc/imx/Makefile sound/soc/imx/imx-cs42888.c sound/soc/imx/imx-esai.c sound/soc/imx/imx-wm8958.c sound/soc/imx/imx-wm8962.c
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/amiserial.c4
-rw-r--r--drivers/tty/moxa.c2
-rw-r--r--drivers/tty/serial/8250_pci.c10
-rw-r--r--drivers/tty/serial/altera_uart.c4
-rw-r--r--drivers/tty/serial/amba-pl011.c29
-rw-r--r--drivers/tty/serial/atmel_serial.c5
-rw-r--r--drivers/tty/serial/clps711x.c14
-rw-r--r--drivers/tty/serial/imx.c16
-rw-r--r--drivers/tty/serial/jsm/jsm_driver.c1
-rw-r--r--drivers/tty/serial/mxs-auart.c2
-rw-r--r--drivers/tty/serial/pch_uart.c7
-rw-r--r--drivers/tty/serial/serial_core.c1
-rw-r--r--drivers/tty/serial/sh-sci.c15
-rw-r--r--drivers/tty/tty_port.c12
-rw-r--r--drivers/tty/vt/consolemap.c51
-rw-r--r--drivers/tty/vt/vt_ioctl.c1
16 files changed, 135 insertions, 39 deletions
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 220579592c20..34111486baac 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -1113,8 +1113,10 @@ static int set_serial_info(struct async_struct * info,
(new_serial.close_delay != state->close_delay) ||
(new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
((new_serial.flags & ~ASYNC_USR_MASK) !=
- (state->flags & ~ASYNC_USR_MASK)))
+ (state->flags & ~ASYNC_USR_MASK))) {
+ tty_unlock();
return -EPERM;
+ }
state->flags = ((state->flags & ~ASYNC_USR_MASK) |
(new_serial.flags & ASYNC_USR_MASK));
info->flags = ((info->flags & ~ASYNC_USR_MASK) |
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
index ba679ce0a774..8f82f7ab3541 100644
--- a/drivers/tty/moxa.c
+++ b/drivers/tty/moxa.c
@@ -1330,7 +1330,7 @@ static void moxa_start(struct tty_struct *tty)
if (ch == NULL)
return;
- if (!(ch->statusflags & TXSTOPPED))
+ if (!test_bit(TXSTOPPED, &ch->statusflags))
return;
MoxaPortTxEnable(ch);
diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c
index ff48fdb5c0bf..21098ed99635 100644
--- a/drivers/tty/serial/8250_pci.c
+++ b/drivers/tty/serial/8250_pci.c
@@ -1459,51 +1459,61 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.vendor = PCI_VENDOR_ID_INTEL,
.device = 0x8811,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = 0x8812,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = 0x8813,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = 0x8814,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x8027,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x8028,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x8029,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x800C,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x800D,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x800D,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
/*
* Cronyx Omega PCI (PLX-chip based)
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 50bc5a5ac653..37db1d5898e0 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -555,7 +555,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res_mem)
port->mapbase = res_mem->start;
- else if (platp->mapbase)
+ else if (platp)
port->mapbase = platp->mapbase;
else
return -EINVAL;
@@ -563,7 +563,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res_irq)
port->irq = res_irq->start;
- else if (platp->irq)
+ else if (platp)
port->irq = platp->irq;
/* Check platform data first so we can override device node data */
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index f5f6831b0a64..21dc4b761eda 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1376,6 +1376,10 @@ static int pl011_startup(struct uart_port *port)
uap->port.uartclk = clk_get_rate(uap->clk);
+ /* Clear pending error and receive interrupts */
+ writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS |
+ UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR);
+
/*
* Allocate the IRQ
*/
@@ -1410,10 +1414,6 @@ static int pl011_startup(struct uart_port *port)
cr = UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
writew(cr, uap->port.membase + UART011_CR);
- /* Clear pending error interrupts */
- writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
- uap->port.membase + UART011_ICR);
-
/*
* initialise the old status of the modem signals
*/
@@ -1428,6 +1428,9 @@ static int pl011_startup(struct uart_port *port)
* as well.
*/
spin_lock_irq(&uap->port.lock);
+ /* Clear out any spuriously appearing RX interrupts */
+ writew(UART011_RTIS | UART011_RXIS,
+ uap->port.membase + UART011_ICR);
uap->im = UART011_RTIM;
if (!pl011_dma_rx_running(uap))
uap->im |= UART011_RXIM;
@@ -1733,9 +1736,19 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
{
struct uart_amba_port *uap = amba_ports[co->index];
unsigned int status, old_cr, new_cr;
+ unsigned long flags;
+ int locked = 1;
clk_enable(uap->clk);
+ local_irq_save(flags);
+ if (uap->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+ locked = spin_trylock(&uap->port.lock);
+ else
+ spin_lock(&uap->port.lock);
+
/*
* First save the CR then disable the interrupts
*/
@@ -1755,6 +1768,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
} while (status & UART01x_FR_BUSY);
writew(old_cr, uap->port.membase + UART011_CR);
+ if (locked)
+ spin_unlock(&uap->port.lock);
+ local_irq_restore(flags);
+
clk_disable(uap->clk);
}
@@ -1906,6 +1923,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
uap->port.line = i;
pl011_dma_probe(uap);
+ /* Ensure interrupts from this UART are masked and cleared */
+ writew(0, uap->port.membase + UART011_IMSC);
+ writew(0xffff, uap->port.membase + UART011_ICR);
+
snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
amba_ports[i] = uap;
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index af9b7814965a..b989495c763e 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -199,8 +199,9 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned int mode;
+ unsigned long flags;
- spin_lock(&port->lock);
+ spin_lock_irqsave(&port->lock, flags);
/* Disable interrupts */
UART_PUT_IDR(port, atmel_port->tx_done_mask);
@@ -231,7 +232,7 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
/* Enable interrupts */
UART_PUT_IER(port, atmel_port->tx_done_mask);
- spin_unlock(&port->lock);
+ spin_unlock_irqrestore(&port->lock, flags);
}
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index e6c3dbd781d6..836fe2731234 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -154,10 +154,9 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id)
port->x_char = 0;
return IRQ_HANDLED;
}
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- clps711xuart_stop_tx(port);
- return IRQ_HANDLED;
- }
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port))
+ goto disable_tx_irq;
count = port->fifosize >> 1;
do {
@@ -171,8 +170,11 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
- if (uart_circ_empty(xmit))
- clps711xuart_stop_tx(port);
+ if (uart_circ_empty(xmit)) {
+ disable_tx_irq:
+ disable_irq_nosync(TX_IRQ(port));
+ tx_enabled(port) = 0;
+ }
return IRQ_HANDLED;
}
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index beba18533371..8a66f3eeb992 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -697,6 +697,9 @@ static unsigned int imx_get_mctrl(struct uart_port *port)
if (readl(sport->port.membase + UCR2) & UCR2_CTS)
tmp |= TIOCM_RTS;
+ if (readl(sport->port.membase + UTS) & UTS_LOOP)
+ tmp |= TIOCM_LOOP;
+
return tmp;
}
@@ -707,10 +710,19 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
temp = readl(sport->port.membase + UCR2) & ~UCR2_CTS;
- if (mctrl & TIOCM_RTS)
+ if (mctrl & TIOCM_RTS) {
temp |= UCR2_CTS;
+ writel(temp, sport->port.membase + UCR2);
+ }
- writel(temp, sport->port.membase + UCR2);
+ if (mctrl & TIOCM_LOOP) {
+ temp = readl(sport->port.membase + UTS) & ~UTS_LOOP;
+ temp |= UTS_LOOP;
+ writel(temp, sport->port.membase + UTS);
+ } else {
+ temp = readl(sport->port.membase + UTS) & ~UTS_LOOP;
+ writel(temp, sport->port.membase + UTS);
+ }
}
/*
diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c
index 2aaafa9c58a2..6c12d94e6d3f 100644
--- a/drivers/tty/serial/jsm/jsm_driver.c
+++ b/drivers/tty/serial/jsm/jsm_driver.c
@@ -269,6 +269,7 @@ static void jsm_io_resume(struct pci_dev *pdev)
struct jsm_board *brd = pci_get_drvdata(pdev);
pci_restore_state(pdev);
+ pci_save_state(pdev);
jsm_uart_port_init(brd);
}
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 7e02c9c344fe..5b3d063a4aa1 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -368,6 +368,8 @@ static void mxs_auart_settermios(struct uart_port *u,
writel(ctrl, u->membase + AUART_LINECTRL);
writel(ctrl2, u->membase + AUART_CTRL2);
+
+ uart_update_timeout(u, termios->c_cflag, baud);
}
static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 902588b2a127..101eda9f1965 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -602,7 +602,8 @@ static void pch_request_dma(struct uart_port *port)
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
- dma_dev = pci_get_bus_and_slot(2, PCI_DEVFN(0xa, 0)); /* Get DMA's dev
+ dma_dev = pci_get_bus_and_slot(priv->pdev->bus->number,
+ PCI_DEVFN(0xa, 0)); /* Get DMA's dev
information */
/* Set Tx DMA */
param = &priv->param_tx;
@@ -1353,9 +1354,11 @@ static int pch_uart_verify_port(struct uart_port *port,
__func__);
return -EOPNOTSUPP;
#endif
- priv->use_dma = 1;
priv->use_dma_flag = 1;
dev_info(priv->port.dev, "PCH UART : Use DMA Mode\n");
+ if (!priv->use_dma)
+ pch_request_dma(port);
+ priv->use_dma = 1;
}
return 0;
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 5668b3eb96d8..2a106a94cdd0 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2328,6 +2328,7 @@ void uart_unregister_driver(struct uart_driver *drv)
tty_unregister_driver(p);
put_tty_driver(p);
kfree(drv->state);
+ drv->state = NULL;
drv->tty_driver = NULL;
}
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index ebd8629c108d..bead17e5634a 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -953,17 +953,20 @@ static void sci_dma_tx_complete(void *arg)
port->icount.tx += sg_dma_len(&s->sg_tx);
async_tx_ack(s->desc_tx);
- s->cookie_tx = -EINVAL;
s->desc_tx = NULL;
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
if (!uart_circ_empty(xmit)) {
+ s->cookie_tx = 0;
schedule_work(&s->work_tx);
- } else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
- u16 ctrl = sci_in(port, SCSCR);
- sci_out(port, SCSCR, ctrl & ~SCSCR_TIE);
+ } else {
+ s->cookie_tx = -EINVAL;
+ if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
+ u16 ctrl = sci_in(port, SCSCR);
+ sci_out(port, SCSCR, ctrl & ~SCSCR_TIE);
+ }
}
spin_unlock_irqrestore(&port->lock, flags);
@@ -1225,8 +1228,10 @@ static void sci_start_tx(struct uart_port *port)
}
if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) &&
- s->cookie_tx < 0)
+ s->cookie_tx < 0) {
+ s->cookie_tx = 0;
schedule_work(&s->work_tx);
+ }
#endif
if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index 33d37d230f8f..a4aaca0e014d 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -227,7 +227,6 @@ int tty_port_block_til_ready(struct tty_port *port,
int do_clocal = 0, retval;
unsigned long flags;
DEFINE_WAIT(wait);
- int cd;
/* block if port is in the process of being closed */
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
@@ -284,11 +283,14 @@ int tty_port_block_til_ready(struct tty_port *port,
retval = -ERESTARTSYS;
break;
}
- /* Probe the carrier. For devices with no carrier detect this
- will always return true */
- cd = tty_port_carrier_raised(port);
+ /*
+ * Probe the carrier. For devices with no carrier detect
+ * tty_port_carrier_raised will always return true.
+ * Never ask drivers if CLOCAL is set, this causes troubles
+ * on some hardware.
+ */
if (!(port->flags & ASYNC_CLOSING) &&
- (do_clocal || cd))
+ (do_clocal || tty_port_carrier_raised(port)))
break;
if (signal_pending(current)) {
retval = -ERESTARTSYS;
diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c
index 45d3e80156d4..f3438083a285 100644
--- a/drivers/tty/vt/consolemap.c
+++ b/drivers/tty/vt/consolemap.c
@@ -516,6 +516,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
int err = 0, err1, i;
struct uni_pagedir *p, *q;
+ /* Save original vc_unipagdir_loc in case we allocate a new one */
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
if (p->readonly) return -EIO;
@@ -528,26 +529,57 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
err1 = con_clear_unimap(vc, NULL);
if (err1) return err1;
+ /*
+ * Since refcount was > 1, con_clear_unimap() allocated a
+ * a new uni_pagedir for this vc. Re: p != q
+ */
q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
- for (i = 0, l = 0; i < 32; i++)
+
+ /*
+ * uni_pgdir is a 32*32*64 table with rows allocated
+ * when its first entry is added. The unicode value must
+ * still be incremented for empty rows. We are copying
+ * entries from "p" (old) to "q" (new).
+ */
+ l = 0; /* unicode value */
+ for (i = 0; i < 32; i++)
if ((p1 = p->uni_pgdir[i]))
for (j = 0; j < 32; j++)
- if ((p2 = p1[j]))
+ if ((p2 = p1[j])) {
for (k = 0; k < 64; k++, l++)
if (p2[k] != 0xffff) {
+ /*
+ * Found one, copy entry for unicode
+ * l with fontpos value p2[k].
+ */
err1 = con_insert_unipair(q, l, p2[k]);
if (err1) {
p->refcount++;
*vc->vc_uni_pagedir_loc = (unsigned long)p;
con_release_unimap(q);
kfree(q);
- return err1;
+ return err1;
}
- }
- p = q;
- } else if (p == dflt)
+ }
+ } else {
+ /* Account for row of 64 empty entries */
+ l += 64;
+ }
+ else
+ /* Account for empty table */
+ l += 32 * 64;
+
+ /*
+ * Finished copying font table, set vc_uni_pagedir to new table
+ */
+ p = q;
+ } else if (p == dflt) {
dflt = NULL;
-
+ }
+
+ /*
+ * Insert user specified unicode pairs into new table.
+ */
while (ct--) {
unsigned short unicode, fontpos;
__get_user(unicode, &list->unicode);
@@ -557,11 +589,14 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
list++;
}
+ /*
+ * Merge with fontmaps of any other virtual consoles.
+ */
if (con_unify_unimap(vc, p))
return err;
for (i = 0; i <= 3; i++)
- set_inverse_transl(vc, p, i); /* Update all inverse translations */
+ set_inverse_transl(vc, p, i); /* Update inverse translations */
set_inverse_trans_unicode(vc, p);
return err;
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index 5e096f43bcea..65447c5f91d7 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -1463,7 +1463,6 @@ compat_kdfontop_ioctl(struct compat_console_font_op __user *fontop,
if (!perm && op->op != KD_FONT_OP_GET)
return -EPERM;
op->data = compat_ptr(((struct compat_console_font_op *)op)->data);
- op->flags |= KD_FONT_FLAG_OLD;
i = con_font_op(vc, op);
if (i)
return i;