Commit 5a22e30d authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'tty-3.3-rc3' tty-next

This is needed to handle the 8250 file merge mess properly for future
patches.
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parents 19e00f2f 418a936e
* Energymicro efm32 UART
Required properties:
- compatible : Should be "efm32,uart"
- reg : Address and length of the register set
- interrupts : Should contain uart interrupt
Example:
uart@0x4000c400 {
compatible = "efm32,uart";
reg = <0x4000c400 0x400>;
interrupts = <15>;
};
...@@ -1015,14 +1015,11 @@ capinc_tty_install(struct tty_driver *driver, struct tty_struct *tty) ...@@ -1015,14 +1015,11 @@ capinc_tty_install(struct tty_driver *driver, struct tty_struct *tty)
{ {
int idx = tty->index; int idx = tty->index;
struct capiminor *mp = capiminor_get(idx); struct capiminor *mp = capiminor_get(idx);
int ret = tty_init_termios(tty); int ret = tty_standard_install(driver, tty);
if (ret == 0) { if (ret == 0)
tty_driver_kref_get(driver);
tty->count++;
tty->driver_data = mp; tty->driver_data = mp;
driver->ttys[idx] = tty; else
} else
capiminor_put(mp); capiminor_put(mp);
return ret; return ret;
} }
......
...@@ -481,13 +481,9 @@ static int pti_tty_install(struct tty_driver *driver, struct tty_struct *tty) ...@@ -481,13 +481,9 @@ static int pti_tty_install(struct tty_driver *driver, struct tty_struct *tty)
{ {
int idx = tty->index; int idx = tty->index;
struct pti_tty *pti_tty_data; struct pti_tty *pti_tty_data;
int ret = tty_init_termios(tty); int ret = tty_standard_install(driver, tty);
if (ret == 0) { if (ret == 0) {
tty_driver_kref_get(driver);
tty->count++;
driver->ttys[idx] = tty;
pti_tty_data = kmalloc(sizeof(struct pti_tty), GFP_KERNEL); pti_tty_data = kmalloc(sizeof(struct pti_tty), GFP_KERNEL);
if (pti_tty_data == NULL) if (pti_tty_data == NULL)
return -ENOMEM; return -ENOMEM;
......
...@@ -750,15 +750,12 @@ static int sdio_uart_install(struct tty_driver *driver, struct tty_struct *tty) ...@@ -750,15 +750,12 @@ static int sdio_uart_install(struct tty_driver *driver, struct tty_struct *tty)
{ {
int idx = tty->index; int idx = tty->index;
struct sdio_uart_port *port = sdio_uart_port_get(idx); struct sdio_uart_port *port = sdio_uart_port_get(idx);
int ret = tty_init_termios(tty); int ret = tty_standard_install(driver, tty);
if (ret == 0) { if (ret == 0)
tty_driver_kref_get(driver);
tty->count++;
/* This is the ref sdio_uart_port get provided */ /* This is the ref sdio_uart_port get provided */
tty->driver_data = port; tty->driver_data = port;
driver->ttys[idx] = tty; else
} else
sdio_uart_port_put(port); sdio_uart_port_put(port);
return ret; return ret;
} }
......
...@@ -113,7 +113,7 @@ static int __init hvc_beat_init(void) ...@@ -113,7 +113,7 @@ static int __init hvc_beat_init(void)
if (!firmware_has_feature(FW_FEATURE_BEAT)) if (!firmware_has_feature(FW_FEATURE_BEAT))
return -ENODEV; return -ENODEV;
hp = hvc_alloc(0, NO_IRQ, &hvc_beat_get_put_ops, 16); hp = hvc_alloc(0, 0, &hvc_beat_get_put_ops, 16);
if (IS_ERR(hp)) if (IS_ERR(hp))
return PTR_ERR(hp); return PTR_ERR(hp);
hvc_beat_dev = hp; hvc_beat_dev = hp;
......
...@@ -94,7 +94,7 @@ static int __init hvc_rtas_init(void) ...@@ -94,7 +94,7 @@ static int __init hvc_rtas_init(void)
/* Allocate an hvc_struct for the console device we instantiated /* Allocate an hvc_struct for the console device we instantiated
* earlier. Save off hp so that we can return it on exit */ * earlier. Save off hp so that we can return it on exit */
hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops, 16); hp = hvc_alloc(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops, 16);
if (IS_ERR(hp)) if (IS_ERR(hp))
return PTR_ERR(hp); return PTR_ERR(hp);
......
...@@ -69,7 +69,7 @@ static int __init hvc_udbg_init(void) ...@@ -69,7 +69,7 @@ static int __init hvc_udbg_init(void)
BUG_ON(hvc_udbg_dev); BUG_ON(hvc_udbg_dev);
hp = hvc_alloc(0, NO_IRQ, &hvc_udbg_ops, 16); hp = hvc_alloc(0, 0, &hvc_udbg_ops, 16);
if (IS_ERR(hp)) if (IS_ERR(hp))
return PTR_ERR(hp); return PTR_ERR(hp);
......
...@@ -176,7 +176,7 @@ static int __init xen_hvc_init(void) ...@@ -176,7 +176,7 @@ static int __init xen_hvc_init(void)
xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn); xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn);
} }
if (xencons_irq < 0) if (xencons_irq < 0)
xencons_irq = 0; /* NO_IRQ */ xencons_irq = 0;
else else
irq_set_noprobe(xencons_irq); irq_set_noprobe(xencons_irq);
......
...@@ -1203,7 +1203,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) ...@@ -1203,7 +1203,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
{ {
struct hvcs_struct *hvcsd; struct hvcs_struct *hvcsd;
unsigned long flags; unsigned long flags;
int irq = NO_IRQ; int irq;
/* /*
* Is someone trying to close the file associated with this device after * Is someone trying to close the file associated with this device after
...@@ -1264,7 +1264,7 @@ static void hvcs_hangup(struct tty_struct * tty) ...@@ -1264,7 +1264,7 @@ static void hvcs_hangup(struct tty_struct * tty)
struct hvcs_struct *hvcsd = tty->driver_data; struct hvcs_struct *hvcsd = tty->driver_data;
unsigned long flags; unsigned long flags;
int temp_open_count; int temp_open_count;
int irq = NO_IRQ; int irq;
spin_lock_irqsave(&hvcsd->lock, flags); spin_lock_irqsave(&hvcsd->lock, flags);
/* Preserve this so that we know how many kref refs to put */ /* Preserve this so that we know how many kref refs to put */
......
...@@ -1237,7 +1237,7 @@ static int __init hvsi_console_init(void) ...@@ -1237,7 +1237,7 @@ static int __init hvsi_console_init(void)
hp->state = HVSI_CLOSED; hp->state = HVSI_CLOSED;
hp->vtermno = *vtermno; hp->vtermno = *vtermno;
hp->virq = irq_create_mapping(NULL, irq[0]); hp->virq = irq_create_mapping(NULL, irq[0]);
if (hp->virq == NO_IRQ) { if (hp->virq == 0) {
printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n", printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n",
__func__, irq[0]); __func__, irq[0]);
continue; continue;
......
...@@ -1602,13 +1602,9 @@ static int ntty_install(struct tty_driver *driver, struct tty_struct *tty) ...@@ -1602,13 +1602,9 @@ static int ntty_install(struct tty_driver *driver, struct tty_struct *tty)
int ret; int ret;
if (!port || !dc || dc->state != NOZOMI_STATE_READY) if (!port || !dc || dc->state != NOZOMI_STATE_READY)
return -ENODEV; return -ENODEV;
ret = tty_init_termios(tty); ret = tty_standard_install(driver, tty);
if (ret == 0) { if (ret == 0)
tty_driver_kref_get(driver);
tty->count++;
tty->driver_data = port; tty->driver_data = port;
driver->ttys[tty->index] = tty;
}
return ret; return ret;
} }
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <linux/major.h> #include <linux/major.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/sysctl.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/bitops.h> #include <linux/bitops.h>
...@@ -55,11 +54,8 @@ static void pty_close(struct tty_struct *tty, struct file *filp) ...@@ -55,11 +54,8 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
wake_up_interruptible(&tty->link->write_wait); wake_up_interruptible(&tty->link->write_wait);
if (tty->driver->subtype == PTY_TYPE_MASTER) { if (tty->driver->subtype == PTY_TYPE_MASTER) {
set_bit(TTY_OTHER_CLOSED, &tty->flags); set_bit(TTY_OTHER_CLOSED, &tty->flags);
#ifdef CONFIG_UNIX98_PTYS
if (tty->driver == ptm_driver)
devpts_pty_kill(tty->link);
#endif
tty_unlock(); tty_unlock();
devpts_pty_kill(tty->link);
tty_vhangup(tty->link); tty_vhangup(tty->link);
tty_lock(); tty_lock();
} }
...@@ -439,55 +435,9 @@ static inline void legacy_pty_init(void) { } ...@@ -439,55 +435,9 @@ static inline void legacy_pty_init(void) { }
/* Unix98 devices */ /* Unix98 devices */
#ifdef CONFIG_UNIX98_PTYS #ifdef CONFIG_UNIX98_PTYS
/*
* sysctl support for setting limits on the number of Unix98 ptys allocated.
* Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly.
*/
int pty_limit = NR_UNIX98_PTY_DEFAULT;
static int pty_limit_min;
static int pty_limit_max = NR_UNIX98_PTY_MAX;
static int pty_count;
static struct cdev ptmx_cdev; static struct cdev ptmx_cdev;
static struct ctl_table pty_table[] = {
{
.procname = "max",
.maxlen = sizeof(int),
.mode = 0644,
.data = &pty_limit,
.proc_handler = proc_dointvec_minmax,
.extra1 = &pty_limit_min,
.extra2 = &pty_limit_max,
}, {
.procname = "nr",
.maxlen = sizeof(int),
.mode = 0444,
.data = &pty_count,
.proc_handler = proc_dointvec,
},
{}
};
static struct ctl_table pty_kern_table[] = {
{
.procname = "pty",
.mode = 0555,
.child = pty_table,
},
{}
};
static struct ctl_table pty_root_table[] = {
{
.procname = "kernel",
.mode = 0555,
.child = pty_kern_table,
},
{}
};
static int pty_unix98_ioctl(struct tty_struct *tty, static int pty_unix98_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
...@@ -515,10 +465,8 @@ static int pty_unix98_ioctl(struct tty_struct *tty, ...@@ -515,10 +465,8 @@ static int pty_unix98_ioctl(struct tty_struct *tty,
static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver, static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver,
struct inode *ptm_inode, int idx) struct inode *ptm_inode, int idx)
{ {
struct tty_struct *tty = devpts_get_tty(ptm_inode, idx); /* Master must be open via /dev/ptmx */
if (tty) return ERR_PTR(-EIO);
tty = tty->link;
return tty;
} }
/** /**
...@@ -589,7 +537,6 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) ...@@ -589,7 +537,6 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
*/ */
tty_driver_kref_get(driver); tty_driver_kref_get(driver);
tty->count++; tty->count++;
pty_count++;
return 0; return 0;
err_free_mem: err_free_mem:
deinitialize_tty_struct(o_tty); deinitialize_tty_struct(o_tty);
...@@ -603,7 +550,6 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) ...@@ -603,7 +550,6 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
static void ptm_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) static void ptm_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
{ {
pty_count--;
} }
static void pts_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) static void pts_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
...@@ -667,9 +613,7 @@ static int ptmx_open(struct inode *inode, struct file *filp) ...@@ -667,9 +613,7 @@ static int ptmx_open(struct inode *inode, struct file *filp)
return retval; return retval;
/* find a device that is not in use. */ /* find a device that is not in use. */
tty_lock();
index = devpts_new_index(inode); index = devpts_new_index(inode);
tty_unlock();
if (index < 0) { if (index < 0) {
retval = index; retval = index;
goto err_file; goto err_file;
...@@ -677,7 +621,7 @@ static int ptmx_open(struct inode *inode, struct file *filp) ...@@ -677,7 +621,7 @@ static int ptmx_open(struct inode *inode, struct file *filp)
mutex_lock(&tty_mutex); mutex_lock(&tty_mutex);
tty_lock(); tty_lock();
tty = tty_init_dev(ptm_driver, index, 1); tty = tty_init_dev(ptm_driver, index);
mutex_unlock(&tty_mutex); mutex_unlock(&tty_mutex);
if (IS_ERR(tty)) { if (IS_ERR(tty)) {
...@@ -704,8 +648,8 @@ static int ptmx_open(struct inode *inode, struct file *filp) ...@@ -704,8 +648,8 @@ static int ptmx_open(struct inode *inode, struct file *filp)
tty_release(inode, filp); tty_release(inode, filp);
return retval; return retval;
out: out:
devpts_kill_index(inode, index);
tty_unlock(); tty_unlock();
devpts_kill_index(inode, index);
err_file: err_file:
tty_free_file(filp); tty_free_file(filp);
return retval; return retval;
...@@ -762,8 +706,6 @@ static void __init unix98_pty_init(void) ...@@ -762,8 +706,6 @@ static void __init unix98_pty_init(void)
if (tty_register_driver(pts_driver)) if (tty_register_driver(pts_driver))
panic("Couldn't register Unix98 pts driver"); panic("Couldn't register Unix98 pts driver");
register_sysctl_table(pty_root_table);
/* Now create the /dev/ptmx special device */ /* Now create the /dev/ptmx special device */
tty_default_fops(&ptmx_fops); tty_default_fops(&ptmx_fops);
ptmx_fops.open = ptmx_open; ptmx_fops.open = ptmx_open;
......
...@@ -331,7 +331,7 @@ static int serial21285_verify_port(struct uart_port *port, struct serial_struct ...@@ -331,7 +331,7 @@ static int serial21285_verify_port(struct uart_port *port, struct serial_struct
int ret = 0; int ret = 0;
if (ser->type != PORT_UNKNOWN && ser->type != PORT_21285) if (ser->type != PORT_UNKNOWN && ser->type != PORT_21285)
ret = -EINVAL; ret = -EINVAL;
if (ser->irq != NO_IRQ) if (ser->irq <= 0)
ret = -EINVAL; ret = -EINVAL;
if (ser->baud_base != port->uartclk / 16) if (ser->baud_base != port->uartclk / 16)
ret = -EINVAL; ret = -EINVAL;
...@@ -360,7 +360,7 @@ static struct uart_ops serial21285_ops = { ...@@ -360,7 +360,7 @@ static struct uart_ops serial21285_ops = {
static struct uart_port serial21285_port = { static struct uart_port serial21285_port = {
.mapbase = 0x42000160, .mapbase = 0x42000160,
.iotype = UPIO_MEM, .iotype = UPIO_MEM,
.irq = NO_IRQ, .irq = 0,
.fifosize = 16, .fifosize = 16,
.ops = &serial21285_ops, .ops = &serial21285_ops,
.flags = UPF_BOOT_AUTOCONF, .flags = UPF_BOOT_AUTOCONF,
......
...@@ -86,13 +86,6 @@ static unsigned int skip_txen_test; /* force skip of txen test at init time */ ...@@ -86,13 +86,6 @@ static unsigned int skip_txen_test; /* force skip of txen test at init time */
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
/*
* We default to IRQ0 for the "no irq" hack. Some
* machine types want others as well - they're free
* to redefine this in their header file.
*/
#define is_real_interrupt(irq) ((irq) != 0)
#ifdef CONFIG_SERIAL_8250_DETECT_IRQ #ifdef CONFIG_SERIAL_8250_DETECT_IRQ
#define CONFIG_SERIAL_DETECT_IRQ 1 #define CONFIG_SERIAL_DETECT_IRQ 1
#endif #endif
...@@ -1750,7 +1743,7 @@ static void serial8250_backup_timeout(unsigned long data) ...@@ -1750,7 +1743,7 @@ static void serial8250_backup_timeout(unsigned long data)
* Must disable interrupts or else we risk racing with the interrupt * Must disable interrupts or else we risk racing with the interrupt
* based handler. * based handler.
*/ */
if (is_real_interrupt(up->port.irq)) { if (up->port.irq) {
ier = serial_in(up, UART_IER); ier = serial_in(up, UART_IER);
serial_out(up, UART_IER, 0); serial_out(up, UART_IER, 0);
} }
...@@ -1775,7 +1768,7 @@ static void serial8250_backup_timeout(unsigned long data) ...@@ -1775,7 +1768,7 @@ static void serial8250_backup_timeout(unsigned long data)
if (!(iir & UART_IIR_NO_INT)) if (!(iir & UART_IIR_NO_INT))
serial8250_tx_chars(up); serial8250_tx_chars(up);
if (is_real_interrupt(up->port.irq)) if (up->port.irq)
serial_out(up, UART_IER, ier); serial_out(up, UART_IER, ier);
spin_unlock_irqrestore(&up->port.lock, flags); spin_unlock_irqrestore(&up->port.lock, flags);
...@@ -2028,7 +2021,7 @@ static int serial8250_startup(struct uart_port *port) ...@@ -2028,7 +2021,7 @@ static int serial8250_startup(struct uart_port *port)
serial_outp(up, UART_LCR, 0); serial_outp(up, UART_LCR, 0);
} }
if (is_real_interrupt(up->port.irq)) { if (up->port.irq) {
unsigned char iir1; unsigned char iir1;
/* /*
* Test for UARTs that do not reassert THRE when the * Test for UARTs that do not reassert THRE when the
...@@ -2083,7 +2076,7 @@ static int serial8250_startup(struct uart_port *port) ...@@ -2083,7 +2076,7 @@ static int serial8250_startup(struct uart_port *port)
* hardware interrupt, we use a timer-based system. The original * hardware interrupt, we use a timer-based system. The original
* driver used to do this with IRQ0. * driver used to do this with IRQ0.
*/ */
if (!is_real_interrupt(up->port.irq)) { if (!up->port.irq) {
up->timer.data = (unsigned long)up; up->timer.data = (unsigned long)up;
mod_timer(&up->timer, jiffies + uart_poll_timeout(port)); mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
} else { } else {
...@@ -2099,13 +2092,13 @@ static int serial8250_startup(struct uart_port *port) ...@@ -2099,13 +2092,13 @@ static int serial8250_startup(struct uart_port *port)
spin_lock_irqsave(&up->port.lock, flags); spin_lock_irqsave(&up->port.lock, flags);
if (up->port.flags & UPF_FOURPORT) { if (up->port.flags & UPF_FOURPORT) {
if (!is_real_interrupt(up->port.irq)) if (!up->port.irq)
up->port.mctrl |= TIOCM_OUT1; up->port.mctrl |= TIOCM_OUT1;
} else } else
/* /*
* Most PC uarts need OUT2 raised to enable interrupts. * Most PC uarts need OUT2 raised to enable interrupts.
*/ */
if (is_real_interrupt(up->port.irq)) if (up->port.irq)
up->port.mctrl |= TIOCM_OUT2; up->port.mctrl |= TIOCM_OUT2;
serial8250_set_mctrl(&up->port, up->port.mctrl); serial8250_set_mctrl(&up->port, up->port.mctrl);
...@@ -2223,7 +2216,7 @@ static void serial8250_shutdown(struct uart_port *port) ...@@ -2223,7 +2216,7 @@ static void serial8250_shutdown(struct uart_port *port)
del_timer_sync(&up->timer); del_timer_sync(&up->timer);
up->timer.function = serial8250_timeout; up->timer.function = serial8250_timeout;
if (is_real_interrupt(up->port.irq)) if (up->port.irq)
serial_unlink_irq_chain(up); serial_unlink_irq_chain(up);
} }
......
...@@ -1347,4 +1347,17 @@ config SERIAL_AR933X_NR_UARTS ...@@ -1347,4 +1347,17 @@ config SERIAL_AR933X_NR_UARTS
Set this to the number of serial ports you want the driver Set this to the number of serial ports you want the driver
to support. to support.
config SERIAL_EFM32_UART
tristate "EFM32 UART/USART port."
depends on ARCH_EFM32
select SERIAL_CORE
help
This driver support the USART and UART ports on
Energy Micro's efm32 SoCs.
config SERIAL_EFM32_UART_CONSOLE
bool "EFM32 UART/USART console support"
depends on SERIAL_EFM32_UART=y
select SERIAL_CORE_CONSOLE
endmenu endmenu
...@@ -61,12 +61,12 @@ obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o ...@@ -61,12 +61,12 @@ obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o
obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
obj-$(CONFIG_SERIAL_QE) += ucc_uart.o obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o
obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o
obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o
obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o
...@@ -78,3 +78,4 @@ obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o ...@@ -78,3 +78,4 @@ obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o
obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o
obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o
obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o
...@@ -377,6 +377,26 @@ static int altera_uart_verify_port(struct uart_port *port, ...@@ -377,6 +377,26 @@ static int altera_uart_verify_port(struct uart_port *port,
return 0; return 0;
} }
#ifdef CONFIG_CONSOLE_POLL
static int altera_uart_poll_get_char(struct uart_port *port)
{
while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
ALTERA_UART_STATUS_RRDY_MSK))
cpu_relax();
return altera_uart_readl(port, ALTERA_UART_RXDATA_REG);
}
static void altera_uart_poll_put_char(struct uart_port *port, unsigned char c)
{
while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
ALTERA_UART_STATUS_TRDY_MSK))
cpu_relax();
altera_uart_writel(port, c, ALTERA_UART_TXDATA_REG);
}
#endif
/* /*
* Define the basic serial functions we support. * Define the basic serial functions we support.
*/ */
...@@ -397,35 +417,16 @@ static struct uart_ops altera_uart_ops = { ...@@ -397,35 +417,16 @@ static struct uart_ops altera_uart_ops = {
.release_port = altera_uart_release_port, .release_port = altera_uart_release_port,
.config_port = altera_uart_config_port, .config_port = altera_uart_config_port,
.verify_port = altera_uart_verify_port, .verify_port = altera_uart_verify_port,
#ifdef CONFIG_CONSOLE_POLL
.poll_get_char = altera_uart_poll_get_char,
.poll_put_char = altera_uart_poll_put_char,
#endif
}; };
static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS]; static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS];
#if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) #if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE)
int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp)
{
struct uart_port *port;
int i;
for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) {
port = &altera_uart_ports[i].port;
port->line = i;
port->type = PORT_ALTERA_UART;
port->mapbase = platp[i].mapbase;
port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
port->iotype = SERIAL_IO_MEM;
port->irq = platp[i].irq;
port->uartclk = platp[i].uartclk;
port->flags = UPF_BOOT_AUTOCONF;
port->ops = &altera_uart_ops;
port->private_data = platp;
}
return 0;
}
static void altera_uart_console_putc(struct uart_port *port, const char c) static void altera_uart_console_putc(struct uart_port *port, const char c)
{ {
while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) & while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
......
This diff is collapsed.
...@@ -70,13 +70,6 @@ ...@@ -70,13 +70,6 @@
#define PASS_LIMIT 256 #define PASS_LIMIT 256
/*
* We default to IRQ0 for the "no irq" hack. Some
* machine types want others as well - they're free
* to redefine this in their header file.
*/
#define is_real_interrupt(irq) ((irq) != 0)
#define BASE_BAUD 115200 #define BASE_BAUD 115200
/* Standard COM flags */ /* Standard COM flags */
...@@ -640,7 +633,7 @@ static int m32r_sio_startup(struct uart_port *port) ...@@ -640,7 +633,7 @@ static int m32r_sio_startup(struct uart_port *port)
* hardware interrupt, we use a timer-based system. The original * hardware interrupt, we use a timer-based system. The original
* driver used to do this with IRQ0. * driver used to do this with IRQ0.
*/ */
if (!is_real_interrupt(up->port.irq)) { if (!up->port.irq) {
unsigned int timeout = up->port.timeout; unsigned int timeout = up->port.timeout;
timeout = timeout > 6 ? (timeout / 2 - 2) : 1; timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
...@@ -687,7 +680,7 @@ static void m32r_sio_shutdown(struct uart_port *port) ...@@ -687,7 +680,7 @@ static void m32r_sio_shutdown(struct uart_port *port)
sio_init(); sio_init();
if (!is_real_interrupt(up->port.irq)) if (!up->port.irq)
del_timer_sync(&up->timer); del_timer_sync(&up->timer);
else else
serial_unlink_irq_chain(up); serial_unlink_irq_chain(up);
......
...@@ -507,7 +507,7 @@ static int __init mpc512x_psc_fifoc_init(void) ...@@ -507,7 +507,7 @@ static int __init mpc512x_psc_fifoc_init(void)
psc_fifoc_irq = irq_of_parse_and_map(np, 0); psc_fifoc_irq = irq_of_parse_and_map(np, 0);
of_node_put(np); of_node_put(np);
if (psc_fifoc_irq == NO_IRQ) { if (psc_fifoc_irq == 0) {
pr_err("%s: Can't get FIFOC irq\n", __func__); pr_err("%s: Can't get FIFOC irq\n", __func__);
iounmap(psc_fifoc); iounmap(psc_fifoc);
return -ENODEV; return -ENODEV;
...@@ -1354,7 +1354,7 @@ static int __devinit mpc52xx_uart_of_probe(struct platform_device *op) ...@@ -1354,7 +1354,7 @@ static int __devinit mpc52xx_uart_of_probe(struct platform_device *op)
} }
psc_ops->get_irq(port, op->dev.of_node); psc_ops->get_irq(port, op->dev.of_node);
if (port->irq == NO_IRQ) { if (port->irq == 0) {
dev_dbg(&op->dev, "Could not get irq\n"); dev_dbg(&op->dev, "Could not get irq\n");
return -EINVAL; return -EINVAL;
} }
......
...@@ -499,7 +499,7 @@ static int __init mux_probe(struct parisc_device *dev) ...@@ -499,7 +499,7 @@ static int __init mux_probe(struct parisc_device *dev)
port->membase = ioremap_nocache(port->mapbase, MUX_LINE_OFFSET); port->membase = ioremap_nocache(port->mapbase, MUX_LINE_OFFSET);
port->iotype = UPIO_MEM; port->iotype = UPIO_MEM;
port->type = PORT_MUX; port->type = PORT_MUX;
port->irq = NO_IRQ; port->irq = 0;
port->uartclk = 0; port->uartclk = 0;
port->fifosize = MUX_FIFO_SIZE; port->fifosize = MUX_FIFO_SIZE;
port->ops = &mux_pops; port->ops = &mux_pops;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/nmi.h> #include <linux/nmi.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/debugfs.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/pch_dma.h> #include <linux/pch_dma.h>
...@@ -144,6 +145,8 @@ enum { ...@@ -144,6 +145,8 @@ enum {
#define PCH_UART_DLL 0x00 #define PCH_UART_DLL 0x00
#define PCH_UART_DLM 0x01 #define PCH_UART_DLM 0x01
#define PCH_UART_BRCSR 0x0E
#define PCH_UART_IID_RLS (PCH_UART_IIR_REI) #define PCH_UART_IID_RLS (PCH_UART_IIR_REI)
#define PCH_UART_IID_RDR (PCH_UART_IIR_RRI) #define PCH_UART_IID_RDR (PCH_UART_IIR_RRI)
#define PCH_UART_IID_RDR_TO (PCH_UART_IIR_RRI | PCH_UART_IIR_TOI) #define PCH_UART_IID_RDR_TO (PCH_UART_IIR_RRI | PCH_UART_IIR_TOI)
...@@ -243,6 +246,8 @@ struct eg20t_port { ...@@ -243,6 +246,8 @@ struct eg20t_port {
int tx_dma_use; int tx_dma_use;
void *rx_buf_virt; void *rx_buf_virt;
dma_addr_t rx_buf_dma; dma_addr_t rx_buf_dma;
struct dentry *debugfs;
}; };
/** /**
...@@ -292,23 +297,73 @@ static const int trigger_level_64[4] = { 1, 16, 32, 56 }; ...@@ -292,23 +297,73 @@ static const int trigger_level_64[4] = { 1, 16, 32, 56 };
static const int trigger_level_16[4] = { 1, 4, 8, 14 }; static const int trigger_level_16[4] = { 1, 4, 8, 14 };
static const int trigger_level_1[4] = { 1, 1, 1, 1 }; static const int trigger_level_1[4] = { 1, 1, 1, 1 };
static void pch_uart_hal_request(struct pci_dev *pdev, int fifosize, #ifdef CONFIG_DEBUG_FS
int base_baud)
{
struct eg20t_port *priv = pci_get_drvdata(pdev);
priv->trigger_level = 1; #define PCH_REGS_BUFSIZE 1024
priv->fcr = 0; static int pch_show_regs_open(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
return 0;
} }
static unsigned int get_msr(struct eg20t_port *priv, void __iomem *base) static ssize_t port_show_regs(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{ {
unsigned int msr = ioread8(base + UART_MSR); struct eg20t_port *priv = file->private_data;
priv->dmsr |= msr & PCH_UART_MSR_DELTA; char *buf;
u32 len = 0;
ssize_t ret;
unsigned char lcr;
buf = kzalloc(PCH_REGS_BUFSIZE, GFP_KERNEL);
if (!buf)
return 0;
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
"PCH EG20T port[%d] regs:\n", priv->port.line);
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
"=================================\n");
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
"IER: \t0x%02x\n", ioread8(priv->membase + UART_IER));
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
"IIR: \t0x%02x\n", ioread8(priv->membase + UART_IIR));
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
"LCR: \t0x%02x\n", ioread8(priv->membase + UART_LCR));
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
"MCR: \t0x%02x\n", ioread8(priv->membase + UART_MCR));
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
"LSR: \t0x%02x\n", ioread8(priv->membase + UART_LSR));
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
"MSR: \t0x%02x\n", ioread8(priv->membase + UART_MSR));
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
"BRCSR: \t0x%02x\n",
ioread8(priv->membase + PCH_UART_BRCSR));
return msr; lcr = ioread8(priv->membase + UART_LCR);
iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR);
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
"DLL: \t0x%02x\n", ioread8(priv->membase + UART_DLL));
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
"DLM: \t0x%02x\n", ioread8(priv->membase + UART_DLM));
iowrite8(lcr, priv->membase + UART_LCR);
if (len > PCH_REGS_BUFSIZE)
len = PCH_REGS_BUFSIZE;
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return ret;
} }
static const struct file_operations port_regs_ops = {
.owner = THIS_MODULE,
.open = pch_show_regs_open,
.read = port_show_regs,
.llseek = default_llseek,
};
#endif /* CONFIG_DEBUG_FS */
static void pch_uart_hal_enable_interrupt(struct eg20t_port *priv, static void pch_uart_hal_enable_interrupt(struct eg20t_port *priv,
unsigned int flag) unsigned int flag)
{ {
...@@ -442,8 +497,9 @@ static int pch_uart_hal_set_fifo(struct eg20t_port *priv, ...@@ -442,8 +497,9 @@ static int pch_uart_hal_set_fifo(struct eg20t_port *priv,
static u8 pch_uart_hal_get_modem(struct eg20t_port *priv) static u8 pch_uart_hal_get_modem(struct eg20t_port *priv)
{ {
priv->dmsr = 0; unsigned int msr = ioread8(priv->membase + UART_MSR);
return get_msr(priv, priv->membase); priv->dmsr = msr & PCH_UART_MSR_DELTA;
return (u8)msr;
} }
static void pch_uart_hal_write(struct eg20t_port *priv, static void pch_uart_hal_write(struct eg20t_port *priv,
...@@ -524,7 +580,7 @@ static int push_rx(struct eg20t_port *priv, const unsigned char *buf, ...@@ -524,7 +580,7 @@ static int push_rx(struct eg20t_port *priv, const unsigned char *buf,
static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf) static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf)
{ {
int ret; int ret = 0;
struct uart_port *port = &priv->port; struct uart_port *port = &priv->port;
if (port->x_char) { if (port->x_char) {
...@@ -533,8 +589,6 @@ static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf) ...@@ -533,8 +589,6 @@ static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf)
buf[0] = port->x_char; buf[0] = port->x_char;
port->x_char = 0; port->x_char = 0;
ret = 1; ret = 1;
} else {
ret = 0;
} }
return ret; return ret;
...@@ -1032,14 +1086,12 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) ...@@ -1032,14 +1086,12 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
static unsigned int pch_uart_tx_empty(struct uart_port *port) static unsigned int pch_uart_tx_empty(struct uart_port *port)
{ {
struct eg20t_port *priv; struct eg20t_port *priv;
int ret;
priv = container_of(port, struct eg20t_port, port); priv = container_of(port, struct eg20t_port, port);
if (priv->tx_empty) if (priv->tx_empty)
ret = TIOCSER_TEMT; return TIOCSER_TEMT;
else else
ret = 0; return 0;
return ret;
} }
/* Returns the current state of modem control inputs. */ /* Returns the current state of modem control inputs. */
...@@ -1273,9 +1325,8 @@ static void pch_uart_set_termios(struct uart_port *port, ...@@ -1273,9 +1325,8 @@ static void pch_uart_set_termios(struct uart_port *port,
else else
parity = PCH_UART_HAL_PARITY_EVEN; parity = PCH_UART_HAL_PARITY_EVEN;
} else { } else
parity = PCH_UART_HAL_PARITY_NONE; parity = PCH_UART_HAL_PARITY_NONE;
}
/* Only UART0 has auto hardware flow function */ /* Only UART0 has auto hardware flow function */
if ((termios->c_cflag & CRTSCTS) && (priv->fifo_size == 256)) if ((termios->c_cflag & CRTSCTS) && (priv->fifo_size == 256))
...@@ -1447,7 +1498,6 @@ static void ...@@ -1447,7 +1498,6 @@ static void
pch_console_write(struct console *co, const char *s, unsigned int count) pch_console_write(struct console *co, const char *s, unsigned int count)
{ {
struct eg20t_port *priv; struct eg20t_port *priv;
unsigned long flags; unsigned long flags;
u8 ier; u8 ier;
int locked = 1; int locked = 1;
...@@ -1554,6 +1604,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, ...@@ -1554,6 +1604,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
int port_type; int port_type;
struct pch_uart_driver_data *board; struct pch_uart_driver_data *board;
const char *board_name; const char *board_name;
char name[32]; /* for debugfs file name */
board = &drv_dat[id->driver_data]; board = &drv_dat[id->driver_data];
port_type = board->port_type; port_type = board->port_type;
...@@ -1614,7 +1665,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, ...@@ -1614,7 +1665,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
spin_lock_init(&priv->port.lock); spin_lock_init(&priv->port.lock);
pci_set_drvdata(pdev, priv); pci_set_drvdata(pdev, priv);
pch_uart_hal_request(pdev, fifosize, base_baud); priv->trigger_level = 1;
priv->fcr = 0;
#ifdef CONFIG_SERIAL_PCH_UART_CONSOLE #ifdef CONFIG_SERIAL_PCH_UART_CONSOLE
pch_uart_ports[board->line_no] = priv; pch_uart_ports[board->line_no] = priv;
...@@ -1623,6 +1675,12 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, ...@@ -1623,6 +1675,12 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
if (ret < 0) if (ret < 0)
goto init_port_hal_free; goto init_port_hal_free;
#ifdef CONFIG_DEBUG_FS
snprintf(name, sizeof(name), "uart%d_regs", board->line_no);
priv->debugfs = debugfs_create_file(name, S_IFREG | S_IRUGO,
NULL, priv, &port_regs_ops);
#endif
return priv; return priv;
init_port_hal_free: init_port_hal_free:
...@@ -1639,6 +1697,11 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, ...@@ -1639,6 +1697,11 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
static void pch_uart_exit_port(struct eg20t_port *priv) static void pch_uart_exit_port(struct eg20t_port *priv)
{ {
#ifdef CONFIG_DEBUG_FS
if (priv->debugfs)
debugfs_remove(priv->debugfs);
#endif
uart_remove_one_port(&pch_uart_driver, &priv->port); uart_remove_one_port(&pch_uart_driver, &priv->port);
pci_set_drvdata(priv->pdev, NULL); pci_set_drvdata(priv->pdev, NULL);
free_page((unsigned long)priv->rxbuf.buf); free_page((unsigned long)priv->rxbuf.buf);
...@@ -1646,9 +1709,7 @@ static void pch_uart_exit_port(struct eg20t_port *priv) ...@@ -1646,9 +1709,7 @@ static void pch_uart_exit_port(struct eg20t_port *priv)
static void pch_uart_pci_remove(struct pci_dev *pdev) static void pch_uart_pci_remove(struct pci_dev *pdev)
{ {
struct eg20t_port *priv; struct eg20t_port *priv = pci_get_drvdata(pdev);
priv = (struct eg20t_port *)pci_get_drvdata(pdev);
pci_disable_msi(pdev); pci_disable_msi(pdev);
......
...@@ -1506,7 +1506,7 @@ static int __init pmz_init_port(struct uart_pmac_port *uap) ...@@ -1506,7 +1506,7 @@ static int __init pmz_init_port(struct uart_pmac_port *uap)
* fixed up interrupt info, but we use the device-tree directly * fixed up interrupt info, but we use the device-tree directly
* here due to early probing so we need the fixup too. * here due to early probing so we need the fixup too.
*/ */
if (uap->port.irq == NO_IRQ && if (uap->port.irq == 0 &&
np->parent && np->parent->parent && np->parent && np->parent->parent &&
of_device_is_compatible(np->parent->parent, "gatwick")) { of_device_is_compatible(np->parent->parent, "gatwick")) {
/* IRQs on gatwick are offset by 64 */ /* IRQs on gatwick are offset by 64 */
......
...@@ -1397,7 +1397,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) ...@@ -1397,7 +1397,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
#endif #endif
} }
static int zilog_irq = -1; static int zilog_irq;
static int __devinit zs_probe(struct platform_device *op) static int __devinit zs_probe(struct platform_device *op)
{ {
...@@ -1425,7 +1425,7 @@ static int __devinit zs_probe(struct platform_device *op) ...@@ -1425,7 +1425,7 @@ static int __devinit zs_probe(struct platform_device *op)
rp = sunzilog_chip_regs[inst]; rp = sunzilog_chip_regs[inst];
if (zilog_irq == -1) if (!zilog_irq)
zilog_irq = op->archdata.irqs[0]; zilog_irq = op->archdata.irqs[0];
up = &sunzilog_port_table[inst * 2]; up = &sunzilog_port_table[inst * 2];
...@@ -1580,7 +1580,7 @@ static int __init sunzilog_init(void) ...@@ -1580,7 +1580,7 @@ static int __init sunzilog_init(void)
if (err) if (err)
goto out_unregister_uart; goto out_unregister_uart;
if (zilog_irq != -1) { if (!zilog_irq) {
struct uart_sunzilog_port *up = sunzilog_irq_chain; struct uart_sunzilog_port *up = sunzilog_irq_chain;
err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED, err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
"zs", sunzilog_irq_chain); "zs", sunzilog_irq_chain);
...@@ -1621,7 +1621,7 @@ static void __exit sunzilog_exit(void) ...@@ -1621,7 +1621,7 @@ static void __exit sunzilog_exit(void)
{ {
platform_driver_unregister(&zs_driver); platform_driver_unregister(&zs_driver);
if (zilog_irq != -1) { if (!zilog_irq) {
struct uart_sunzilog_port *up = sunzilog_irq_chain; struct uart_sunzilog_port *up = sunzilog_irq_chain;
/* Disable Interrupts */ /* Disable Interrupts */
...@@ -1637,7 +1637,7 @@ static void __exit sunzilog_exit(void) ...@@ -1637,7 +1637,7 @@ static void __exit sunzilog_exit(void)
} }
free_irq(zilog_irq, sunzilog_irq_chain); free_irq(zilog_irq, sunzilog_irq_chain);
zilog_irq = -1; zilog_irq = 0;
} }
if (sunzilog_reg.nr) { if (sunzilog_reg.nr) {
......
...@@ -1360,7 +1360,7 @@ static int ucc_uart_probe(struct platform_device *ofdev) ...@@ -1360,7 +1360,7 @@ static int ucc_uart_probe(struct platform_device *ofdev)
} }
qe_port->port.irq = irq_of_parse_and_map(np, 0); qe_port->port.irq = irq_of_parse_and_map(np, 0);
if (qe_port->port.irq == NO_IRQ) { if (qe_port->port.irq == 0) {
dev_err(&ofdev->dev, "could not map IRQ for UCC%u\n", dev_err(&ofdev->dev, "could not map IRQ for UCC%u\n",
qe_port->ucc_num + 1); qe_port->ucc_num + 1);
ret = -EINVAL; ret = -EINVAL;
......
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
static struct uart_port siu_uart_ports[SIU_PORTS_MAX] = { static struct uart_port siu_uart_ports[SIU_PORTS_MAX] = {
[0 ... SIU_PORTS_MAX-1] = { [0 ... SIU_PORTS_MAX-1] = {
.lock = __SPIN_LOCK_UNLOCKED(siu_uart_ports->lock), .lock = __SPIN_LOCK_UNLOCKED(siu_uart_ports->lock),
.irq = -1, .irq = 0,
}, },
}; };
...@@ -171,7 +171,7 @@ static inline unsigned int siu_check_type(struct uart_port *port) ...@@ -171,7 +171,7 @@ static inline unsigned int siu_check_type(struct uart_port *port)
{ {
if (port->line == 0) if (port->line == 0)
return PORT_VR41XX_SIU; return PORT_VR41XX_SIU;
if (port->line == 1 && port->irq != -1) if (port->line == 1 && port->irq)
return PORT_VR41XX_DSIU; return PORT_VR41XX_DSIU;
return PORT_UNKNOWN; return PORT_UNKNOWN;
......
...@@ -322,11 +322,16 @@ static void send_sig_all(int sig) ...@@ -322,11 +322,16 @@ static void send_sig_all(int sig)
{ {
struct task_struct *p; struct task_struct *p;
read_lock(&tasklist_lock);
for_each_process(p) { for_each_process(p) {
if (p->mm && !is_global_init(p)) if (p->flags & PF_KTHREAD)
/* Not swapper, init nor kernel thread */ continue;
force_sig(sig, p); if (is_global_init(p))
continue;
force_sig(sig, p);
} }
read_unlock(&tasklist_lock);
} }
static void sysrq_handle_term(int key) static void sysrq_handle_term(int key)
......
...@@ -1271,6 +1271,19 @@ int tty_init_termios(struct tty_struct *tty) ...@@ -1271,6 +1271,19 @@ int tty_init_termios(struct tty_struct *tty)
} }
EXPORT_SYMBOL_GPL(tty_init_termios); EXPORT_SYMBOL_GPL(tty_init_termios);
int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty)
{
int ret = tty_init_termios(tty);
if (ret)
return ret;
tty_driver_kref_get(driver);
tty->count++;
driver->ttys[tty->index] = tty;
return 0;
}
EXPORT_SYMBOL_GPL(tty_standard_install);
/** /**
* tty_driver_install_tty() - install a tty entry in the driver * tty_driver_install_tty() - install a tty entry in the driver
* @driver: the driver for the tty * @driver: the driver for the tty
...@@ -1286,21 +1299,8 @@ EXPORT_SYMBOL_GPL(tty_init_termios); ...@@ -1286,21 +1299,8 @@ EXPORT_SYMBOL_GPL(tty_init_termios);
static int tty_driver_install_tty(struct tty_driver *driver, static int tty_driver_install_tty(struct tty_driver *driver,
struct tty_struct *tty) struct tty_struct *tty)
{ {
int idx = tty->index; return driver->ops->install ? driver->ops->install(driver, tty) :
int ret; tty_standard_install(driver, tty);
if (driver->ops->install) {
ret = driver->ops->install(driver, tty);
return ret;
}
if (tty_init_termios(tty) == 0) {
tty_driver_kref_get(driver);
tty->count++;
driver->ttys[idx] = tty;
return 0;
}
return -ENOMEM;
} }
/** /**
...@@ -1365,7 +1365,6 @@ static int tty_reopen(struct tty_struct *tty) ...@@ -1365,7 +1365,6 @@ static int tty_reopen(struct tty_struct *tty)
* @driver: tty driver we are opening a device on * @driver: tty driver we are opening a device on
* @idx: device index * @idx: device index
* @ret_tty: returned tty structure * @ret_tty: returned tty structure
* @first_ok: ok to open a new device (used by ptmx)
* *
* Prepare a tty device. This may not be a "new" clean device but * Prepare a tty device. This may not be a "new" clean device but
* could also be an active device. The pty drivers require special * could also be an active device. The pty drivers require special
...@@ -1385,18 +1384,11 @@ static int tty_reopen(struct tty_struct *tty) ...@@ -1385,18 +1384,11 @@ static int tty_reopen(struct tty_struct *tty)
* relaxed for the (most common) case of reopening a tty. * relaxed for the (most common) case of reopening a tty.
*/ */
struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
int first_ok)
{ {
struct tty_struct *tty; struct tty_struct *tty;
int retval; int retval;
/* Check if pty master is being opened multiple times */
if (driver->subtype == PTY_TYPE_MASTER &&
(driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) {
return ERR_PTR(-EIO);
}
/* /*
* First time open is complex, especially for PTY devices. * First time open is complex, especially for PTY devices.
* This code guarantees that either everything succeeds and the * This code guarantees that either everything succeeds and the
...@@ -1797,11 +1789,11 @@ int tty_release(struct inode *inode, struct file *filp) ...@@ -1797,11 +1789,11 @@ int tty_release(struct inode *inode, struct file *filp)
* the slots and preserving the termios structure. * the slots and preserving the termios structure.
*/ */
release_tty(tty, idx); release_tty(tty, idx);
tty_unlock();
/* Make this pty number available for reallocation */ /* Make this pty number available for reallocation */
if (devpts) if (devpts)
devpts_kill_index(inode, idx); devpts_kill_index(inode, idx);
tty_unlock();
return 0; return 0;
} }
...@@ -1950,7 +1942,7 @@ static int tty_open(struct inode *inode, struct file *filp) ...@@ -1950,7 +1942,7 @@ static int tty_open(struct inode *inode, struct file *filp)
if (retval) if (retval)
tty = ERR_PTR(retval); tty = ERR_PTR(retval);
} else } else
tty = tty_init_dev(driver, index, 0); tty = tty_init_dev(driver, index);
mutex_unlock(&tty_mutex); mutex_unlock(&tty_mutex);
if (driver) if (driver)
......
...@@ -214,15 +214,14 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) ...@@ -214,15 +214,14 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
if (!try_module_get(serial->type->driver.owner)) if (!try_module_get(serial->type->driver.owner))
goto error_module_get; goto error_module_get;
/* perform the standard setup */
retval = tty_init_termios(tty);
if (retval)
goto error_init_termios;
retval = usb_autopm_get_interface(serial->interface); retval = usb_autopm_get_interface(serial->interface);
if (retval) if (retval)
goto error_get_interface; goto error_get_interface;
retval = tty_standard_install(driver, tty);
if (retval)
goto error_init_termios;
mutex_unlock(&serial->disc_mutex); mutex_unlock(&serial->disc_mutex);
/* allow the driver to update the settings */ /* allow the driver to update the settings */
...@@ -231,14 +230,11 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) ...@@ -231,14 +230,11 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
tty->driver_data = port; tty->driver_data = port;
/* Final install (we use the default method) */
tty_driver_kref_get(driver);
tty->count++;
driver->ttys[idx] = tty;
return retval; return retval;
error_get_interface:
error_init_termios: error_init_termios:
usb_autopm_put_interface(serial->interface);
error_get_interface:
module_put(serial->type->driver.owner); module_put(serial->type->driver.owner);
error_module_get: error_module_get:
error_no_port: error_no_port:
......
...@@ -36,7 +36,61 @@ ...@@ -36,7 +36,61 @@
#define DEVPTS_DEFAULT_PTMX_MODE 0000 #define DEVPTS_DEFAULT_PTMX_MODE 0000
#define PTMX_MINOR 2 #define PTMX_MINOR 2
extern int pty_limit; /* Config limit on Unix98 ptys */ /*
* sysctl support for setting limits on the number of Unix98 ptys allocated.
* Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly.
*/
static int pty_limit = NR_UNIX98_PTY_DEFAULT;
static int pty_reserve = NR_UNIX98_PTY_RESERVE;
static int pty_limit_min;
static int pty_limit_max = INT_MAX;
static int pty_count;
static struct ctl_table pty_table[] = {
{
.procname = "max",
.maxlen = sizeof(int),
.mode = 0644,
.data = &pty_limit,
.proc_handler = proc_dointvec_minmax,
.extra1 = &pty_limit_min,
.extra2 = &pty_limit_max,
}, {
.procname = "reserve",
.maxlen = sizeof(int),
.mode = 0644,
.data = &pty_reserve,
.proc_handler = proc_dointvec_minmax,
.extra1 = &pty_limit_min,
.extra2 = &pty_limit_max,
}, {
.procname = "nr",
.maxlen = sizeof(int),
.mode = 0444,
.data = &pty_count,
.proc_handler = proc_dointvec,
},
{}
};
static struct ctl_table pty_kern_table[] = {
{
.procname = "pty",
.mode = 0555,
.child = pty_table,
},
{}
};
static struct ctl_table pty_root_table[] = {
{
.procname = "kernel",
.mode = 0555,
.child = pty_kern_table,
},
{}
};
static DEFINE_MUTEX(allocated_ptys_lock); static DEFINE_MUTEX(allocated_ptys_lock);
static struct vfsmount *devpts_mnt; static struct vfsmount *devpts_mnt;
...@@ -49,10 +103,11 @@ struct pts_mount_opts { ...@@ -49,10 +103,11 @@ struct pts_mount_opts {
umode_t mode; umode_t mode;
umode_t ptmxmode; umode_t ptmxmode;
int newinstance; int newinstance;
int max;
}; };
enum { enum {
Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance, Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance, Opt_max,
Opt_err Opt_err
}; };
...@@ -63,6 +118,7 @@ static const match_table_t tokens = { ...@@ -63,6 +118,7 @@ static const match_table_t tokens = {
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
{Opt_ptmxmode, "ptmxmode=%o"}, {Opt_ptmxmode, "ptmxmode=%o"},
{Opt_newinstance, "newinstance"}, {Opt_newinstance, "newinstance"},
{Opt_max, "max=%d"},
#endif #endif
{Opt_err, NULL} {Opt_err, NULL}
}; };
...@@ -109,6 +165,7 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts) ...@@ -109,6 +165,7 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
opts->gid = 0; opts->gid = 0;
opts->mode = DEVPTS_DEFAULT_MODE; opts->mode = DEVPTS_DEFAULT_MODE;
opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE; opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
opts->max = NR_UNIX98_PTY_MAX;
/* newinstance makes sense only on initial mount */ /* newinstance makes sense only on initial mount */
if (op == PARSE_MOUNT) if (op == PARSE_MOUNT)
...@@ -152,6 +209,12 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts) ...@@ -152,6 +209,12 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
if (op == PARSE_MOUNT) if (op == PARSE_MOUNT)
opts->newinstance = 1; opts->newinstance = 1;
break; break;
case Opt_max:
if (match_int(&args[0], &option) ||
option < 0 || option > NR_UNIX98_PTY_MAX)
return -EINVAL;
opts->max = option;
break;
#endif #endif
default: default:
printk(KERN_ERR "devpts: called with bogus options\n"); printk(KERN_ERR "devpts: called with bogus options\n");
...@@ -258,6 +321,8 @@ static int devpts_show_options(struct seq_file *seq, struct dentry *root) ...@@ -258,6 +321,8 @@ static int devpts_show_options(struct seq_file *seq, struct dentry *root)
seq_printf(seq, ",mode=%03o", opts->mode); seq_printf(seq, ",mode=%03o", opts->mode);
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode); seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode);
if (opts->max < NR_UNIX98_PTY_MAX)
seq_printf(seq, ",max=%d", opts->max);
#endif #endif
return 0; return 0;
...@@ -438,6 +503,12 @@ int devpts_new_index(struct inode *ptmx_inode) ...@@ -438,6 +503,12 @@ int devpts_new_index(struct inode *ptmx_inode)
return -ENOMEM; return -ENOMEM;
mutex_lock(&allocated_ptys_lock); mutex_lock(&allocated_ptys_lock);
if (pty_count >= pty_limit -
(fsi->mount_opts.newinstance ? pty_reserve : 0)) {
mutex_unlock(&allocated_ptys_lock);
return -ENOSPC;
}
ida_ret = ida_get_new(&fsi->allocated_ptys, &index); ida_ret = ida_get_new(&fsi->allocated_ptys, &index);
if (ida_ret < 0) { if (ida_ret < 0) {
mutex_unlock(&allocated_ptys_lock); mutex_unlock(&allocated_ptys_lock);
...@@ -446,11 +517,12 @@ int devpts_new_index(struct inode *ptmx_inode) ...@@ -446,11 +517,12 @@ int devpts_new_index(struct inode *ptmx_inode)
return -EIO; return -EIO;
} }
if (index >= pty_limit) { if (index >= fsi->mount_opts.max) {
ida_remove(&fsi->allocated_ptys, index); ida_remove(&fsi->allocated_ptys, index);
mutex_unlock(&allocated_ptys_lock); mutex_unlock(&allocated_ptys_lock);
return -EIO; return -ENOSPC;
} }
pty_count++;
mutex_unlock(&allocated_ptys_lock); mutex_unlock(&allocated_ptys_lock);
return index; return index;
} }
...@@ -462,6 +534,7 @@ void devpts_kill_index(struct inode *ptmx_inode, int idx) ...@@ -462,6 +534,7 @@ void devpts_kill_index(struct inode *ptmx_inode, int idx)
mutex_lock(&allocated_ptys_lock); mutex_lock(&allocated_ptys_lock);
ida_remove(&fsi->allocated_ptys, idx); ida_remove(&fsi->allocated_ptys, idx);
pty_count--;
mutex_unlock(&allocated_ptys_lock); mutex_unlock(&allocated_ptys_lock);
} }
...@@ -558,11 +631,15 @@ void devpts_pty_kill(struct tty_struct *tty) ...@@ -558,11 +631,15 @@ void devpts_pty_kill(struct tty_struct *tty)
static int __init init_devpts_fs(void) static int __init init_devpts_fs(void)
{ {
int err = register_filesystem(&devpts_fs_type); int err = register_filesystem(&devpts_fs_type);
struct ctl_table_header *table;
if (!err) { if (!err) {
table = register_sysctl_table(pty_root_table);
devpts_mnt = kern_mount(&devpts_fs_type); devpts_mnt = kern_mount(&devpts_fs_type);
if (IS_ERR(devpts_mnt)) { if (IS_ERR(devpts_mnt)) {
err = PTR_ERR(devpts_mnt); err = PTR_ERR(devpts_mnt);
unregister_filesystem(&devpts_fs_type); unregister_filesystem(&devpts_fs_type);
unregister_sysctl_table(table);
} }
} }
return err; return err;
......
...@@ -5,8 +5,6 @@ ...@@ -5,8 +5,6 @@
#ifndef __ALTUART_H #ifndef __ALTUART_H
#define __ALTUART_H #define __ALTUART_H
#include <linux/init.h>
struct altera_uart_platform_uart { struct altera_uart_platform_uart {
unsigned long mapbase; /* Physical address base */ unsigned long mapbase; /* Physical address base */
unsigned int irq; /* Interrupt vector */ unsigned int irq; /* Interrupt vector */
...@@ -14,6 +12,4 @@ struct altera_uart_platform_uart { ...@@ -14,6 +12,4 @@ struct altera_uart_platform_uart {
unsigned int bus_shift; /* Bus shift (address stride) */ unsigned int bus_shift; /* Bus shift (address stride) */
}; };
int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp);
#endif /* __ALTUART_H */ #endif /* __ALTUART_H */
/*
*
*
*/
#ifndef __LINUX_PLATFORM_DATA_EFM32_UART_H__
#define __LINUX_PLATFORM_DATA_EFM32_UART_H__
#include <linux/types.h>
/**
* struct efm32_uart_pdata
* @location: pinmux location for the I/O pins (to be written to the ROUTE
* register)
*/
struct efm32_uart_pdata {
u8 location;
};
#endif /* ifndef __LINUX_PLATFORM_DATA_EFM32_UART_H__ */
...@@ -210,6 +210,8 @@ ...@@ -210,6 +210,8 @@
/* Atheros AR933X SoC */ /* Atheros AR933X SoC */
#define PORT_AR933X 99 #define PORT_AR933X 99
/* Energy Micro efm32 SoC */
#define PORT_EFMUART 100
#ifdef __KERNEL__ #ifdef __KERNEL__
......
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
* hardcoded at present.) * hardcoded at present.)
*/ */
#define NR_UNIX98_PTY_DEFAULT 4096 /* Default maximum for Unix98 ptys */ #define NR_UNIX98_PTY_DEFAULT 4096 /* Default maximum for Unix98 ptys */
#define NR_UNIX98_PTY_RESERVE 1024 /* Default reserve for main devpts */
#define NR_UNIX98_PTY_MAX (1 << MINORBITS) /* Absolute limit */ #define NR_UNIX98_PTY_MAX (1 << MINORBITS) /* Absolute limit */
/* /*
...@@ -480,10 +481,11 @@ extern void free_tty_struct(struct tty_struct *tty); ...@@ -480,10 +481,11 @@ extern void free_tty_struct(struct tty_struct *tty);
extern void initialize_tty_struct(struct tty_struct *tty, extern void initialize_tty_struct(struct tty_struct *tty,
struct tty_driver *driver, int idx); struct tty_driver *driver, int idx);
extern void deinitialize_tty_struct(struct tty_struct *tty); extern void deinitialize_tty_struct(struct tty_struct *tty);
extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx);
int first_ok);
extern int tty_release(struct inode *inode, struct file *filp); extern int tty_release(struct inode *inode, struct file *filp);
extern int tty_init_termios(struct tty_struct *tty); extern int tty_init_termios(struct tty_struct *tty);
extern int tty_standard_install(struct tty_driver *driver,
struct tty_struct *tty);
extern struct tty_struct *tty_pair_get_tty(struct tty_struct *tty); extern struct tty_struct *tty_pair_get_tty(struct tty_struct *tty);
extern struct tty_struct *tty_pair_get_pty(struct tty_struct *tty); extern struct tty_struct *tty_pair_get_pty(struct tty_struct *tty);
......
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