Commit d9795562 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull tty/serial fixes from Greg Kroah-Hartman:
 "Here are some tty / serial driver fixes for 3.10-rc2.

  Nothing huge, although the rocket driver fix looks large, it's just
  moving the code around to fix the reported build issues in it.  Other
  than that, this has the fix for the of-reported lockdep warning from
  the vt layer, as well as some other needed bugfixes.

  All of these have been in linux-next for a while"

* tag 'tty-3.10-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  tty: mxser: Fix build warning introduced by dfc7b837 (Re: linux-next: build warning after merge of the tty.current tree)
  tty: mxser: fix usage of opmode_ioaddr
  serial: 8250_dw: add ACPI ID for Intel BayTrail
  TTY: Fix tty miss restart after we turn off flow-control
  tty/vt: Fix vc_deallocate() lock order
  TTY: ehv_bytechan: add missing platform_driver_unregister() when module exit
  TTY: rocket, fix more no-PCI warnings
  serial: mcf: missing uart_unregister_driver() on error in mcf_init()
  tty: serial: mpc5xxx: fix error handing in mpc52xx_uart_init()
  serial: samsung: add missing platform_driver_unregister() when module exit
  serial: pl011: protect attribute read from NULL platform data struct
  tty: nwpserial: Pass correct pointer to free_irq()
  serial: 8250_dw: Add valid clk pointer check
parents 388c2896 e037f95f
...@@ -859,6 +859,7 @@ static int __init ehv_bc_init(void) ...@@ -859,6 +859,7 @@ static int __init ehv_bc_init(void)
*/ */
static void __exit ehv_bc_exit(void) static void __exit ehv_bc_exit(void)
{ {
platform_driver_unregister(&ehv_bc_tty_driver);
tty_unregister_driver(ehv_bc_driver); tty_unregister_driver(ehv_bc_driver);
put_tty_driver(ehv_bc_driver); put_tty_driver(ehv_bc_driver);
kfree(bcs); kfree(bcs);
......
...@@ -1618,8 +1618,12 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) ...@@ -1618,8 +1618,12 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
if (ip->type == PORT_16550A) if (ip->type == PORT_16550A)
me->fifo[p] = 1; me->fifo[p] = 1;
opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2); if (ip->board->chip_flag == MOXA_MUST_MU860_HWID) {
opmode &= OP_MODE_MASK; opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2);
opmode &= OP_MODE_MASK;
} else {
opmode = RS232_MODE;
}
me->iftype[p] = opmode; me->iftype[p] = opmode;
mutex_unlock(&port->mutex); mutex_unlock(&port->mutex);
} }
...@@ -1676,6 +1680,9 @@ static int mxser_ioctl(struct tty_struct *tty, ...@@ -1676,6 +1680,9 @@ static int mxser_ioctl(struct tty_struct *tty,
int shiftbit; int shiftbit;
unsigned char val, mask; unsigned char val, mask;
if (info->board->chip_flag != MOXA_MUST_MU860_HWID)
return -EFAULT;
p = tty->index % 4; p = tty->index % 4;
if (cmd == MOXA_SET_OP_MODE) { if (cmd == MOXA_SET_OP_MODE) {
if (get_user(opmode, (int __user *) argp)) if (get_user(opmode, (int __user *) argp))
......
...@@ -1573,6 +1573,14 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) ...@@ -1573,6 +1573,14 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
ldata->real_raw = 0; ldata->real_raw = 0;
} }
n_tty_set_room(tty); n_tty_set_room(tty);
/*
* 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) {
start_tty(tty);
}
/* The termios change make the tty ready for I/O */ /* The termios change make the tty ready for I/O */
wake_up_interruptible(&tty->write_wait); wake_up_interruptible(&tty->write_wait);
wake_up_interruptible(&tty->read_wait); wake_up_interruptible(&tty->read_wait);
......
This diff is collapsed.
...@@ -338,7 +338,8 @@ static int dw8250_runtime_suspend(struct device *dev) ...@@ -338,7 +338,8 @@ static int dw8250_runtime_suspend(struct device *dev)
{ {
struct dw8250_data *data = dev_get_drvdata(dev); struct dw8250_data *data = dev_get_drvdata(dev);
clk_disable_unprepare(data->clk); if (!IS_ERR(data->clk))
clk_disable_unprepare(data->clk);
return 0; return 0;
} }
...@@ -347,7 +348,8 @@ static int dw8250_runtime_resume(struct device *dev) ...@@ -347,7 +348,8 @@ static int dw8250_runtime_resume(struct device *dev)
{ {
struct dw8250_data *data = dev_get_drvdata(dev); struct dw8250_data *data = dev_get_drvdata(dev);
clk_prepare_enable(data->clk); if (!IS_ERR(data->clk))
clk_prepare_enable(data->clk);
return 0; return 0;
} }
...@@ -367,6 +369,7 @@ MODULE_DEVICE_TABLE(of, dw8250_of_match); ...@@ -367,6 +369,7 @@ MODULE_DEVICE_TABLE(of, dw8250_of_match);
static const struct acpi_device_id dw8250_acpi_match[] = { static const struct acpi_device_id dw8250_acpi_match[] = {
{ "INT33C4", 0 }, { "INT33C4", 0 },
{ "INT33C5", 0 }, { "INT33C5", 0 },
{ "80860F0A", 0 },
{ }, { },
}; };
MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match); MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
......
...@@ -332,7 +332,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port * ...@@ -332,7 +332,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
dmaengine_slave_config(chan, &rx_conf); dmaengine_slave_config(chan, &rx_conf);
uap->dmarx.chan = chan; uap->dmarx.chan = chan;
if (plat->dma_rx_poll_enable) { if (plat && plat->dma_rx_poll_enable) {
/* Set poll rate if specified. */ /* Set poll rate if specified. */
if (plat->dma_rx_poll_rate) { if (plat->dma_rx_poll_rate) {
uap->dmarx.auto_poll_rate = false; uap->dmarx.auto_poll_rate = false;
......
...@@ -707,8 +707,10 @@ static int __init mcf_init(void) ...@@ -707,8 +707,10 @@ static int __init mcf_init(void)
if (rc) if (rc)
return rc; return rc;
rc = platform_driver_register(&mcf_platform_driver); rc = platform_driver_register(&mcf_platform_driver);
if (rc) if (rc) {
uart_unregister_driver(&mcf_driver);
return rc; return rc;
}
return 0; return 0;
} }
......
...@@ -1497,18 +1497,23 @@ mpc52xx_uart_init(void) ...@@ -1497,18 +1497,23 @@ mpc52xx_uart_init(void)
if (psc_ops && psc_ops->fifoc_init) { if (psc_ops && psc_ops->fifoc_init) {
ret = psc_ops->fifoc_init(); ret = psc_ops->fifoc_init();
if (ret) if (ret)
return ret; goto err_init;
} }
ret = platform_driver_register(&mpc52xx_uart_of_driver); ret = platform_driver_register(&mpc52xx_uart_of_driver);
if (ret) { if (ret) {
printk(KERN_ERR "%s: platform_driver_register failed (%i)\n", printk(KERN_ERR "%s: platform_driver_register failed (%i)\n",
__FILE__, ret); __FILE__, ret);
uart_unregister_driver(&mpc52xx_uart_driver); goto err_reg;
return ret;
} }
return 0; return 0;
err_reg:
if (psc_ops && psc_ops->fifoc_uninit)
psc_ops->fifoc_uninit();
err_init:
uart_unregister_driver(&mpc52xx_uart_driver);
return ret;
} }
static void __exit static void __exit
......
...@@ -199,7 +199,7 @@ static void nwpserial_shutdown(struct uart_port *port) ...@@ -199,7 +199,7 @@ static void nwpserial_shutdown(struct uart_port *port)
dcr_write(up->dcr_host, UART_IER, up->ier); dcr_write(up->dcr_host, UART_IER, up->ier);
/* free irq */ /* free irq */
free_irq(up->port.irq, port); free_irq(up->port.irq, up);
} }
static int nwpserial_verify_port(struct uart_port *port, static int nwpserial_verify_port(struct uart_port *port,
......
...@@ -1803,6 +1803,7 @@ static int __init s3c24xx_serial_modinit(void) ...@@ -1803,6 +1803,7 @@ static int __init s3c24xx_serial_modinit(void)
static void __exit s3c24xx_serial_modexit(void) static void __exit s3c24xx_serial_modexit(void)
{ {
platform_driver_unregister(&samsung_serial_driver);
uart_unregister_driver(&s3c24xx_uart_drv); uart_unregister_driver(&s3c24xx_uart_drv);
} }
......
...@@ -779,7 +779,6 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ ...@@ -779,7 +779,6 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
con_set_default_unimap(vc); con_set_default_unimap(vc);
vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL); vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
if (!vc->vc_screenbuf) { if (!vc->vc_screenbuf) {
tty_port_destroy(&vc->port);
kfree(vc); kfree(vc);
vc_cons[currcons].d = NULL; vc_cons[currcons].d = NULL;
return -ENOMEM; return -ENOMEM;
...@@ -986,26 +985,25 @@ static int vt_resize(struct tty_struct *tty, struct winsize *ws) ...@@ -986,26 +985,25 @@ static int vt_resize(struct tty_struct *tty, struct winsize *ws)
return ret; return ret;
} }
void vc_deallocate(unsigned int currcons) struct vc_data *vc_deallocate(unsigned int currcons)
{ {
struct vc_data *vc = NULL;
WARN_CONSOLE_UNLOCKED(); WARN_CONSOLE_UNLOCKED();
if (vc_cons_allocated(currcons)) { if (vc_cons_allocated(currcons)) {
struct vc_data *vc = vc_cons[currcons].d; struct vt_notifier_param param;
struct vt_notifier_param param = { .vc = vc };
param.vc = vc = vc_cons[currcons].d;
atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, &param); atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, &param);
vcs_remove_sysfs(currcons); vcs_remove_sysfs(currcons);
vc->vc_sw->con_deinit(vc); vc->vc_sw->con_deinit(vc);
put_pid(vc->vt_pid); put_pid(vc->vt_pid);
module_put(vc->vc_sw->owner); module_put(vc->vc_sw->owner);
kfree(vc->vc_screenbuf); kfree(vc->vc_screenbuf);
if (currcons >= MIN_NR_CONSOLES) {
tty_port_destroy(&vc->port);
kfree(vc);
}
vc_cons[currcons].d = NULL; vc_cons[currcons].d = NULL;
} }
return vc;
} }
/* /*
......
...@@ -283,6 +283,51 @@ do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_ ...@@ -283,6 +283,51 @@ do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_
return 0; return 0;
} }
/* deallocate a single console, if possible (leave 0) */
static int vt_disallocate(unsigned int vc_num)
{
struct vc_data *vc = NULL;
int ret = 0;
if (!vc_num)
return 0;
console_lock();
if (VT_BUSY(vc_num))
ret = -EBUSY;
else
vc = vc_deallocate(vc_num);
console_unlock();
if (vc && vc_num >= MIN_NR_CONSOLES) {
tty_port_destroy(&vc->port);
kfree(vc);
}
return ret;
}
/* deallocate all unused consoles, but leave 0 */
static void vt_disallocate_all(void)
{
struct vc_data *vc[MAX_NR_CONSOLES];
int i;
console_lock();
for (i = 1; i < MAX_NR_CONSOLES; i++)
if (!VT_BUSY(i))
vc[i] = vc_deallocate(i);
else
vc[i] = NULL;
console_unlock();
for (i = 1; i < MAX_NR_CONSOLES; i++) {
if (vc[i] && i >= MIN_NR_CONSOLES) {
tty_port_destroy(&vc[i]->port);
kfree(vc[i]);
}
}
}
/* /*
...@@ -769,24 +814,10 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -769,24 +814,10 @@ int vt_ioctl(struct tty_struct *tty,
ret = -ENXIO; ret = -ENXIO;
break; break;
} }
if (arg == 0) { if (arg == 0)
/* deallocate all unused consoles, but leave 0 */ vt_disallocate_all();
console_lock(); else
for (i=1; i<MAX_NR_CONSOLES; i++) ret = vt_disallocate(--arg);
if (! VT_BUSY(i))
vc_deallocate(i);
console_unlock();
} else {
/* deallocate a single console, if possible */
arg--;
if (VT_BUSY(arg))
ret = -EBUSY;
else if (arg) { /* leave 0 */
console_lock();
vc_deallocate(arg);
console_unlock();
}
}
break; break;
case VT_RESIZE: case VT_RESIZE:
......
...@@ -36,7 +36,7 @@ extern int fg_console, last_console, want_console; ...@@ -36,7 +36,7 @@ extern int fg_console, last_console, want_console;
int vc_allocate(unsigned int console); int vc_allocate(unsigned int console);
int vc_cons_allocated(unsigned int console); int vc_cons_allocated(unsigned int console);
int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines); int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
void vc_deallocate(unsigned int console); struct vc_data *vc_deallocate(unsigned int console);
void reset_palette(struct vc_data *vc); void reset_palette(struct vc_data *vc);
void do_blank_screen(int entering_gfx); void do_blank_screen(int entering_gfx);
void do_unblank_screen(int leaving_gfx); void do_unblank_screen(int leaving_gfx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment