summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt14
-rw-r--r--Documentation/devicetree/bindings/tty/serial/of-serial.txt1
-rw-r--r--arch/um/drivers/chan_kern.c4
-rw-r--r--arch/um/drivers/line.c32
-rw-r--r--arch/um/drivers/line.h3
-rw-r--r--drivers/tty/amiserial.c14
-rw-r--r--drivers/tty/cyclades.c65
-rw-r--r--drivers/tty/n_r3964.c10
-rw-r--r--drivers/tty/n_tty.c6
-rw-r--r--drivers/tty/pty.c164
-rw-r--r--drivers/tty/serial/8250/8250.c88
-rw-r--r--drivers/tty/serial/8250/8250.h1
-rw-r--r--drivers/tty/serial/8250/8250_acorn.c22
-rw-r--r--drivers/tty/serial/8250/8250_dw.c38
-rw-r--r--drivers/tty/serial/8250/8250_gsc.c26
-rw-r--r--drivers/tty/serial/8250/8250_hp300.c26
-rw-r--r--drivers/tty/serial/8250/8250_pci.c126
-rw-r--r--drivers/tty/serial/8250/8250_pnp.c28
-rw-r--r--drivers/tty/serial/8250/serial_cs.c30
-rw-r--r--drivers/tty/serial/Kconfig19
-rw-r--r--drivers/tty/serial/Makefile1
-rw-r--r--drivers/tty/serial/amba-pl011.c34
-rw-r--r--drivers/tty/serial/crisv10.c8
-rw-r--r--drivers/tty/serial/imx.c2
-rw-r--r--drivers/tty/serial/lpc32xx_hs.c823
-rw-r--r--drivers/tty/serial/of_serial.c1
-rw-r--r--drivers/tty/serial/pch_uart.c38
-rw-r--r--drivers/tty/serial/pxa.c14
-rw-r--r--drivers/tty/serial/samsung.c28
-rw-r--r--drivers/tty/serial/serial_core.c6
-rw-r--r--drivers/tty/synclink.c4
-rw-r--r--drivers/tty/synclink_gt.c4
-rw-r--r--drivers/tty/synclinkmp.c4
-rw-r--r--drivers/tty/tty_io.c101
-rw-r--r--drivers/tty/tty_ldisc.c69
-rw-r--r--drivers/tty/tty_mutex.c71
-rw-r--r--drivers/tty/tty_port.c23
-rw-r--r--drivers/tty/vt/keyboard.c9
-rw-r--r--drivers/tty/vt/vt.c62
-rw-r--r--drivers/tty/vt/vt_ioctl.c47
-rw-r--r--drivers/usb/serial/metro-usb.c8
-rw-r--r--drivers/usb/serial/usb-serial.c2
-rw-r--r--include/linux/Kbuild3
-rw-r--r--include/linux/cd1400.h292
-rw-r--r--include/linux/cdk.h486
-rw-r--r--include/linux/comstats.h119
-rw-r--r--include/linux/generic_serial.h35
-rw-r--r--include/linux/istallion.h123
-rw-r--r--include/linux/kbd_kern.h12
-rw-r--r--include/linux/sc26198.h533
-rw-r--r--include/linux/serial167.h157
-rw-r--r--include/linux/serial_8250.h1
-rw-r--r--include/linux/serial_core.h3
-rw-r--r--include/linux/stallion.h147
-rw-r--r--include/linux/tty.h28
-rw-r--r--include/linux/tty_driver.h1
-rw-r--r--include/net/irda/ircomm_tty.h17
-rw-r--r--net/bluetooth/rfcomm/tty.c4
-rw-r--r--net/irda/ircomm/ircomm_param.c5
-rw-r--r--net/irda/ircomm/ircomm_tty.c271
-rw-r--r--net/irda/ircomm/ircomm_tty_attach.c40
-rw-r--r--net/irda/ircomm/ircomm_tty_ioctl.c25
62 files changed, 1742 insertions, 2636 deletions
diff --git a/Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt b/Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt
new file mode 100644
index 000000000000..0d439dfc1aa5
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt
@@ -0,0 +1,14 @@
+* NXP LPC32xx SoC High Speed UART
+
+Required properties:
+- compatible: Should be "nxp,lpc3220-hsuart"
+- reg: Should contain registers location and length
+- interrupts: Should contain interrupt
+
+Example:
+
+ uart1: serial@40014000 {
+ compatible = "nxp,lpc3220-hsuart";
+ reg = <0x40014000 0x1000>;
+ interrupts = <26 0>;
+ };
diff --git a/Documentation/devicetree/bindings/tty/serial/of-serial.txt b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
index b8b27b0aca10..0847fdeee11a 100644
--- a/Documentation/devicetree/bindings/tty/serial/of-serial.txt
+++ b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
@@ -9,6 +9,7 @@ Required properties:
- "ns16750"
- "ns16850"
- "nvidia,tegra20-uart"
+ - "nxp,lpc3220-uart"
- "ibm,qpace-nwp-serial"
- "serial" if the port type is unknown.
- reg : offset and length of the register set for the device.
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 45e248c2f43c..87eebfe03c61 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -150,9 +150,11 @@ void chan_enable_winch(struct chan *chan, struct tty_struct *tty)
static void line_timer_cb(struct work_struct *work)
{
struct line *line = container_of(work, struct line, task.work);
+ struct tty_struct *tty = tty_port_tty_get(&line->port);
if (!line->throttled)
- chan_interrupt(line, line->tty, line->driver->read_irq);
+ chan_interrupt(line, tty, line->driver->read_irq);
+ tty_kref_put(tty);
}
int enable_chan(struct line *line)
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index acfd0e0fd0c9..fb6e4ea09921 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -19,9 +19,11 @@ static irqreturn_t line_interrupt(int irq, void *data)
{
struct chan *chan = data;
struct line *line = chan->line;
+ struct tty_struct *tty = tty_port_tty_get(&line->port);
if (line)
- chan_interrupt(line, line->tty, irq);
+ chan_interrupt(line, tty, irq);
+ tty_kref_put(tty);
return IRQ_HANDLED;
}
@@ -333,7 +335,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
{
struct chan *chan = data;
struct line *line = chan->line;
- struct tty_struct *tty = line->tty;
+ struct tty_struct *tty;
int err;
/*
@@ -352,10 +354,13 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
}
spin_unlock(&line->lock);
+ tty = tty_port_tty_get(&line->port);
if (tty == NULL)
return IRQ_NONE;
tty_wakeup(tty);
+ tty_kref_put(tty);
+
return IRQ_HANDLED;
}
@@ -404,12 +409,12 @@ int line_open(struct line *lines, struct tty_struct *tty)
goto out_unlock;
err = 0;
- if (line->count++)
+ if (line->port.count++)
goto out_unlock;
BUG_ON(tty->driver_data);
tty->driver_data = line;
- line->tty = tty;
+ tty_port_tty_set(&line->port, tty);
err = enable_chan(line);
if (err) /* line_close() will be called by our caller */
@@ -446,10 +451,10 @@ void line_close(struct tty_struct *tty, struct file * filp)
mutex_lock(&line->count_lock);
BUG_ON(!line->valid);
- if (--line->count)
+ if (--line->port.count)
goto out_unlock;
- line->tty = NULL;
+ tty_port_tty_set(&line->port, NULL);
tty->driver_data = NULL;
if (line->sigio) {
@@ -478,7 +483,7 @@ int setup_one_line(struct line *lines, int n, char *init,
mutex_lock(&line->count_lock);
- if (line->count) {
+ if (line->port.count) {
*error_out = "Device is already open";
goto out;
}
@@ -610,9 +615,15 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
mutex_lock(&line->count_lock);
if (!line->valid)
CONFIG_CHUNK(str, size, n, "none", 1);
- else if (line->tty == NULL)
- CONFIG_CHUNK(str, size, n, line->init_str, 1);
- else n = chan_config_string(line, str, size, error_out);
+ else {
+ struct tty_struct *tty = tty_port_tty_get(&line->port);
+ if (tty == NULL) {
+ CONFIG_CHUNK(str, size, n, line->init_str, 1);
+ } else {
+ n = chan_config_string(line, str, size, error_out);
+ tty_kref_put(tty);
+ }
+ }
mutex_unlock(&line->count_lock);
return n;
@@ -663,6 +674,7 @@ int register_lines(struct line_driver *line_driver,
driver->init_termios = tty_std_termios;
for (i = 0; i < nlines; i++) {
+ tty_port_init(&lines[i].port);
spin_lock_init(&lines[i].lock);
mutex_init(&lines[i].count_lock);
lines[i].driver = line_driver;
diff --git a/arch/um/drivers/line.h b/arch/um/drivers/line.h
index 0a1834719dba..5b3d4fbdec18 100644
--- a/arch/um/drivers/line.h
+++ b/arch/um/drivers/line.h
@@ -32,9 +32,8 @@ struct line_driver {
};
struct line {
- struct tty_struct *tty;
+ struct tty_port port;
struct mutex count_lock;
- unsigned long count;
int valid;
char *init_str;
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 6cc4358f68c1..35819e312624 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -1033,7 +1033,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state,
if (!retinfo)
return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
- tty_lock();
+ tty_lock(tty);
tmp.line = tty->index;
tmp.port = state->port;
tmp.flags = state->tport.flags;
@@ -1042,7 +1042,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state,
tmp.close_delay = state->tport.close_delay;
tmp.closing_wait = state->tport.closing_wait;
tmp.custom_divisor = state->custom_divisor;
- tty_unlock();
+ tty_unlock(tty);
if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
return -EFAULT;
return 0;
@@ -1059,12 +1059,12 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
return -EFAULT;
- tty_lock();
+ tty_lock(tty);
change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) ||
new_serial.custom_divisor != state->custom_divisor;
if (new_serial.irq || new_serial.port != state->port ||
new_serial.xmit_fifo_size != state->xmit_fifo_size) {
- tty_unlock();
+ tty_unlock(tty);
return -EINVAL;
}
@@ -1074,7 +1074,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
(new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
((new_serial.flags & ~ASYNC_USR_MASK) !=
(port->flags & ~ASYNC_USR_MASK))) {
- tty_unlock();
+ tty_unlock(tty);
return -EPERM;
}
port->flags = ((port->flags & ~ASYNC_USR_MASK) |
@@ -1084,7 +1084,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
}
if (new_serial.baud_base < 9600) {
- tty_unlock();
+ tty_unlock(tty);
return -EINVAL;
}
@@ -1116,7 +1116,7 @@ check_and_exit:
}
} else
retval = startup(tty, state);
- tty_unlock();
+ tty_unlock(tty);
return retval;
}
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
index e61cabdd69df..69e9ca2dd4b3 100644
--- a/drivers/tty/cyclades.c
+++ b/drivers/tty/cyclades.c
@@ -1599,7 +1599,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
* If the port is the middle of closing, bail out now
*/
if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
- wait_event_interruptible_tty(info->port.close_wait,
+ wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
}
@@ -3289,6 +3289,7 @@ static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr,
static int __init cy_detect_isa(void)
{
#ifdef CONFIG_ISA
+ struct cyclades_card *card;
unsigned short cy_isa_irq, nboard;
void __iomem *cy_isa_address;
unsigned short i, j, cy_isa_nchan;
@@ -3349,7 +3350,8 @@ static int __init cy_detect_isa(void)
}
/* fill the next cy_card structure available */
for (j = 0; j < NR_CARDS; j++) {
- if (cy_card[j].base_addr == NULL)
+ card = &cy_card[j];
+ if (card->base_addr == NULL)
break;
}
if (j == NR_CARDS) { /* no more cy_cards available */
@@ -3363,7 +3365,7 @@ static int __init cy_detect_isa(void)
/* allocate IRQ */
if (request_irq(cy_isa_irq, cyy_interrupt,
- 0, "Cyclom-Y", &cy_card[j])) {
+ 0, "Cyclom-Y", card)) {
printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but "
"could not allocate IRQ#%d.\n",
(unsigned long)cy_isa_address, cy_isa_irq);
@@ -3372,16 +3374,16 @@ static int __init cy_detect_isa(void)
}
/* set cy_card */
- cy_card[j].base_addr = cy_isa_address;
- cy_card[j].ctl_addr.p9050 = NULL;
- cy_card[j].irq = (int)cy_isa_irq;
- cy_card[j].bus_index = 0;
- cy_card[j].first_line = cy_next_channel;
- cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
- cy_card[j].nports = cy_isa_nchan;
- if (cy_init_card(&cy_card[j])) {
- cy_card[j].base_addr = NULL;
- free_irq(cy_isa_irq, &cy_card[j]);
+ card->base_addr = cy_isa_address;
+ card->ctl_addr.p9050 = NULL;
+ card->irq = (int)cy_isa_irq;
+ card->bus_index = 0;
+ card->first_line = cy_next_channel;
+ card->num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
+ card->nports = cy_isa_nchan;
+ if (cy_init_card(card)) {
+ card->base_addr = NULL;
+ free_irq(cy_isa_irq, card);
iounmap(cy_isa_address);
continue;
}
@@ -3695,6 +3697,7 @@ err:
static int __devinit cy_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
+ struct cyclades_card *card;
void __iomem *addr0 = NULL, *addr2 = NULL;
char *card_name = NULL;
u32 uninitialized_var(mailbox);
@@ -3829,7 +3832,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
}
/* fill the next cy_card structure available */
for (card_no = 0; card_no < NR_CARDS; card_no++) {
- if (cy_card[card_no].base_addr == NULL)
+ card = &cy_card[card_no];
+ if (card->base_addr == NULL)
break;
}
if (card_no == NR_CARDS) { /* no more cy_cards available */
@@ -3843,27 +3847,26 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
/* allocate IRQ */
retval = request_irq(irq, cyy_interrupt,
- IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]);
+ IRQF_SHARED, "Cyclom-Y", card);
if (retval) {
dev_err(&pdev->dev, "could not allocate IRQ\n");
goto err_unmap;
}
- cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP;
+ card->num_chips = nchan / CyPORTS_PER_CHIP;
} else {
struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS;
struct ZFW_CTRL __iomem *zfw_ctrl;
zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
- cy_card[card_no].hw_ver = mailbox;
- cy_card[card_no].num_chips = (unsigned int)-1;
- cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl;
+ card->hw_ver = mailbox;
+ card->num_chips = (unsigned int)-1;
+ card->board_ctrl = &zfw_ctrl->board_ctrl;
#ifdef CONFIG_CYZ_INTR
/* allocate IRQ only if board has an IRQ */
if (irq != 0 && irq != 255) {
retval = request_irq(irq, cyz_interrupt,
- IRQF_SHARED, "Cyclades-Z",
- &cy_card[card_no]);
+ IRQF_SHARED, "Cyclades-Z", card);
if (retval) {
dev_err(&pdev->dev, "could not allocate IRQ\n");
goto err_unmap;
@@ -3873,17 +3876,17 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
}
/* set cy_card */
- cy_card[card_no].base_addr = addr2;
- cy_card[card_no].ctl_addr.p9050 = addr0;
- cy_card[card_no].irq = irq;
- cy_card[card_no].bus_index = 1;
- cy_card[card_no].first_line = cy_next_channel;
- cy_card[card_no].nports = nchan;
- retval = cy_init_card(&cy_card[card_no]);
+ card->base_addr = addr2;
+ card->ctl_addr.p9050 = addr0;
+ card->irq = irq;
+ card->bus_index = 1;
+ card->first_line = cy_next_channel;
+ card->nports = nchan;
+ retval = cy_init_card(card);
if (retval)
goto err_null;
- pci_set_drvdata(pdev, &cy_card[card_no]);
+ pci_set_drvdata(pdev, card);
if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
@@ -3915,8 +3918,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
return 0;
err_null:
- cy_card[card_no].base_addr = NULL;
- free_irq(irq, &cy_card[card_no]);
+ card->base_addr = NULL;
+ free_irq(irq, card);
err_unmap:
iounmap(addr0);
if (addr2)
diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c
index 5c6c31459a2f..1e6405070ce6 100644
--- a/drivers/tty/n_r3964.c
+++ b/drivers/tty/n_r3964.c
@@ -1065,7 +1065,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
TRACE_L("read()");
- tty_lock();
+ tty_lock(tty);
pClient = findClient(pInfo, task_pid(current));
if (pClient) {
@@ -1077,7 +1077,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
goto unlock;
}
/* block until there is a message: */
- wait_event_interruptible_tty(pInfo->read_wait,
+ wait_event_interruptible_tty(tty, pInfo->read_wait,
(pMsg = remove_msg(pInfo, pClient)));
}
@@ -1107,7 +1107,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
}
ret = -EPERM;
unlock:
- tty_unlock();
+ tty_unlock(tty);
return ret;
}
@@ -1156,7 +1156,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
pHeader->locks = 0;
pHeader->owner = NULL;
- tty_lock();
+ tty_lock(tty);
pClient = findClient(pInfo, task_pid(current));
if (pClient) {
@@ -1175,7 +1175,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
add_tx_queue(pInfo, pHeader);
trigger_transmit(pInfo);
- tty_unlock();
+ tty_unlock(tty);
return 0;
}
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index ee1c268f5f9d..4f34491b65c6 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -1432,6 +1432,12 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
*/
if (tty->receive_room < TTY_THRESHOLD_THROTTLE)
tty_throttle(tty);
+
+ /* FIXME: there is a tiny race here if the receive room check runs
+ before the other work executes and empties the buffer (upping
+ the receiving room and unthrottling. We then throttle and get
+ stuck. This has been observed and traced down by Vincent Pillet/
+ We need to address this when we sort out out the rx path locking */
}
int is_ignored(int sig)
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 5505ffc91da4..a0ca0830cbcf 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -47,6 +47,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
wake_up_interruptible(&tty->read_wait);
wake_up_interruptible(&tty->write_wait);
tty->packet = 0;
+ /* Review - krefs on tty_link ?? */
if (!tty->link)
return;
tty->link->packet = 0;
@@ -62,9 +63,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
mutex_unlock(&devpts_mutex);
}
#endif
- tty_unlock();
+ tty_unlock(tty);
tty_vhangup(tty->link);
- tty_lock();
+ tty_lock(tty);
}
}
@@ -282,60 +283,98 @@ done:
return 0;
}
-/* Traditional BSD devices */
-#ifdef CONFIG_LEGACY_PTYS
-
-static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
+static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
+ bool legacy)
{
struct tty_struct *o_tty;
+ struct tty_port *ports[2];
int idx = tty->index;
- int retval;
+ int retval = -ENOMEM;
o_tty = alloc_tty_struct();
- if (!o_tty)
- return -ENOMEM;
+ ports[0] = kmalloc(sizeof **ports, GFP_KERNEL);
+ ports[1] = kmalloc(sizeof **ports, GFP_KERNEL);
+ if (!o_tty || !ports[0] || !ports[1])
+ goto err_free_tty;
if (!try_module_get(driver->other->owner)) {
/* This cannot in fact currently happen */
- retval = -ENOMEM;
goto err_free_tty;
}
initialize_tty_struct(o_tty, driver->other, idx);
- /* We always use new tty termios data so we can do this
- the easy way .. */
- retval = tty_init_termios(tty);
- if (retval)
- goto err_deinit_tty;
-
- retval = tty_init_termios(o_tty);
- if (retval)
- goto err_free_termios;
+ if (legacy) {
+ /* We always use new tty termios data so we can do this
+ the easy way .. */
+ retval = tty_init_termios(tty);
+ if (retval)
+ goto err_deinit_tty;
+
+ retval = tty_init_termios(o_tty);
+ if (retval)
+ goto err_free_termios;
+
+ driver->other->ttys[idx] = o_tty;
+ driver->ttys[idx] = tty;
+ } else {
+ tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
+ if (tty->termios == NULL)
+ goto err_deinit_tty;
+ *tty->termios = driver->init_termios;
+ tty->termios_locked = tty->termios + 1;
+
+ o_tty->termios = kzalloc(sizeof(struct ktermios[2]),
+ GFP_KERNEL);
+ if (o_tty->termios == NULL)
+ goto err_free_termios;
+ *o_tty->termios = driver->other->init_termios;
+ o_tty->termios_locked = o_tty->termios + 1;
+ }
/*
* Everything allocated ... set up the o_tty structure.
*/
- driver->other->ttys[idx] = o_tty;
tty_driver_kref_get(driver->other);
if (driver->subtype == PTY_TYPE_MASTER)
o_tty->count++;
/* Establish the links in both directions */
tty->link = o_tty;
o_tty->link = tty;
+ tty_port_init(ports[0]);
+ tty_port_init(ports[1]);
+ o_tty->port = ports[0];
+ tty->port = ports[1];
tty_driver_kref_get(driver);
tty->count++;
- driver->ttys[idx] = tty;
return 0;
err_free_termios:
- tty_free_termios(tty);
+ if (legacy)
+ tty_free_termios(tty);
+ else
+ kfree(tty->termios);
err_deinit_tty:
deinitialize_tty_struct(o_tty);
module_put(o_tty->driver->owner);
err_free_tty:
+ kfree(ports[0]);
+ kfree(ports[1]);
free_tty_struct(o_tty);
return retval;
}
+static void pty_cleanup(struct tty_struct *tty)
+{
+ kfree(tty->port);
+}
+
+/* Traditional BSD devices */
+#ifdef CONFIG_LEGACY_PTYS
+
+static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+ return pty_common_install(driver, tty, true);
+}
+
static int pty_bsd_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
@@ -366,6 +405,7 @@ static const struct tty_operations master_pty_ops_bsd = {
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
.ioctl = pty_bsd_ioctl,
+ .cleanup = pty_cleanup,
.resize = pty_resize
};
@@ -379,6 +419,7 @@ static const struct tty_operations slave_pty_ops_bsd = {
.chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
+ .cleanup = pty_cleanup,
.resize = pty_resize
};
@@ -509,66 +550,17 @@ static void pty_unix98_shutdown(struct tty_struct *tty)
static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
{
- struct tty_struct *o_tty;
- int idx = tty->index;
-
- o_tty = alloc_tty_struct();
- if (!o_tty)
- return -ENOMEM;
- if (!try_module_get(driver->other->owner)) {
- /* This cannot in fact currently happen */
- goto err_free_tty;
- }
- initialize_tty_struct(o_tty, driver->other, idx);
-
- tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
- if (tty->termios == NULL)
- goto err_free_mem;
- *tty->termios = driver->init_termios;
- tty->termios_locked = tty->termios + 1;
-
- o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
- if (o_tty->termios == NULL)
- goto err_free_mem;
- *o_tty->termios = driver->other->init_termios;
- o_tty->termios_locked = o_tty->termios + 1;
-
- tty_driver_kref_get(driver->other);
- if (driver->subtype == PTY_TYPE_MASTER)
- o_tty->count++;
- /* Establish the links in both directions */
- tty->link = o_tty;
- o_tty->link = tty;
- /*
- * All structures have been allocated, so now we install them.
- * Failures after this point use release_tty to clean up, so
- * there's no need to null out the local pointers.
- */
- tty_driver_kref_get(driver);
- tty->count++;
- return 0;
-err_free_mem:
- deinitialize_tty_struct(o_tty);
- kfree(o_tty->termios);
- kfree(tty->termios);
- module_put(o_tty->driver->owner);
-err_free_tty:
- free_tty_struct(o_tty);
- return -ENOMEM;
-}
-
-static void ptm_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
-{
+ return pty_common_install(driver, tty, false);
}
-static void pts_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
+static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
{
}
static const struct tty_operations ptm_unix98_ops = {
.lookup = ptm_unix98_lookup,
.install = pty_unix98_install,
- .remove = ptm_unix98_remove,
+ .remove = pty_unix98_remove,
.open = pty_open,
.close = pty_close,
.write = pty_write,
@@ -579,13 +571,14 @@ static const struct tty_operations ptm_unix98_ops = {
.set_termios = pty_set_termios,
.ioctl = pty_unix98_ioctl,
.shutdown = pty_unix98_shutdown,
+ .cleanup = pty_cleanup,
.resize = pty_resize
};
static const struct tty_operations pty_unix98_ops = {
.lookup = pts_unix98_lookup,
.install = pty_unix98_install,
- .remove = pts_unix98_remove,
+ .remove = pty_unix98_remove,
.open = pty_open,
.close = pty_close,
.write = pty_write,
@@ -594,7 +587,8 @@ static const struct tty_operations pty_unix98_ops = {
.chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
- .shutdown = pty_unix98_shutdown
+ .shutdown = pty_unix98_shutdown,
+ .cleanup = pty_cleanup,
};
/**
@@ -622,26 +616,26 @@ static int ptmx_open(struct inode *inode, struct file *filp)
return retval;
/* find a device that is not in use. */
- tty_lock();
+ mutex_lock(&devpts_mutex);
index = devpts_new_index(inode);
- tty_unlock();
+ mutex_unlock(&devpts_mutex);
if (index < 0) {
retval = index;
goto err_file;
}
mutex_lock(&tty_mutex);
- mutex_lock(&devpts_mutex);
tty = tty_init_dev(ptm_driver, index);
- mutex_unlock(&devpts_mutex);
- tty_lock();
- mutex_unlock(&tty_mutex);
if (IS_ERR(tty)) {
retval = PTR_ERR(tty);
goto out;
}
+ /* The tty returned here is locked so we can safely
+ drop the mutex */
+ mutex_unlock(&tty_mutex);
+
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
tty_add_file(tty, filp);
@@ -654,15 +648,15 @@ static int ptmx_open(struct inode *inode, struct file *filp)
if (retval)
goto err_release;
- tty_unlock();
+ tty_unlock(tty);
return 0;
err_release:
- tty_unlock();
+ tty_unlock(tty);
tty_release(inode, filp);
return retval;
out:
+ mutex_unlock(&tty_mutex);
devpts_kill_index(inode, index);
- tty_unlock();
err_file:
tty_free_file(filp);
return retval;
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 6e1958a325bd..44f52c6f15b9 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -282,6 +282,14 @@ static const struct serial8250_config uart_config[] = {
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR,
},
+ [PORT_LPC3220] = {
+ .name = "LPC3220",
+ .fifo_size = 64,
+ .tx_loadsz = 32,
+ .fcr = UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO |
+ UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00,
+ .flags = UART_CAP_FIFO,
+ },
};
/* Uart divisor latch read */
@@ -2194,6 +2202,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
unsigned char cval, fcr = 0;
unsigned long flags;
unsigned int baud, quot;
+ int fifo_bug = 0;
switch (termios->c_cflag & CSIZE) {
case CS5:
@@ -2213,8 +2222,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
if (termios->c_cflag & CSTOPB)
cval |= UART_LCR_STOP;
- if (termios->c_cflag & PARENB)
+ if (termios->c_cflag & PARENB) {
cval |= UART_LCR_PARITY;
+ if (up->bugs & UART_BUG_PARITY)
+ fifo_bug = 1;
+ }
if (!(termios->c_cflag & PARODD))
cval |= UART_LCR_EPAR;
#ifdef CMSPAR
@@ -2238,7 +2250,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
fcr = uart_config[port->type].fcr;
- if (baud < 2400) {
+ if (baud < 2400 || fifo_bug) {
fcr &= ~UART_FCR_TRIGGER_MASK;
fcr |= UART_FCR_TRIGGER_1;
}
@@ -2971,36 +2983,36 @@ void serial8250_resume_port(int line)
static int __devinit serial8250_probe(struct platform_device *dev)
{
struct plat_serial8250_port *p = dev->dev.platform_data;
- struct uart_port port;
+ struct uart_8250_port uart;
int ret, i, irqflag = 0;
- memset(&port, 0, sizeof(struct uart_port));
+ memset(&uart, 0, sizeof(uart));
if (share_irqs)
irqflag = IRQF_SHARED;
for (i = 0; p && p->flags != 0; p++, i++) {
- port.iobase = p->iobase;
- port.membase = p->membase;
- port.irq = p->irq;
- port.irqflags = p->irqflags;
- port.uartclk = p->uartclk;
- port.regshift = p->regshift;
- port.iotype = p->iotype;
- port.flags = p->flags;
- port.mapbase = p->mapbase;
- port.hub6 = p->hub6;
- port.private_data = p->private_data;
- port.type = p->type;
- port.serial_in = p->serial_in;
- port.serial_out = p->serial_out;
- port.handle_irq = p->handle_irq;
- port.handle_break = p->handle_break;
- port.set_termios = p->set_termios;
- port.pm = p->pm;
- port.dev = &dev->dev;
- port.irqflags |= irqflag;
- ret = serial8250_register_port(&port);
+ uart.port.iobase = p->iobase;
+ uart.port.membase = p->membase;
+ uart.port.irq = p->irq;
+ uart.port.irqflags = p->irqflags;
+ uart.port.uartclk = p->uartclk;
+ uart.port.regshift = p->regshift;
+ uart.port.iotype = p->iotype;
+ uart.port.flags = p->flags;
+ uart.port.mapbase = p->mapbase;
+ uart.port.hub6 = p->hub6;
+ uart.port.private_data = p->private_data;
+ uart.port.type = p->type;
+ uart.port.serial_in = p->serial_in;
+ uart.port.serial_out = p->serial_out;
+ uart.port.handle_irq = p->handle_irq;
+ uart.port.handle_break = p->handle_break;
+ uart.port.set_termios = p->set_termios;
+ uart.port.pm = p->pm;
+ uart.port.dev = &dev->dev;
+ uart.port.irqflags |= irqflag;
+ ret = serial8250_register_8250_port(&uart);
if (ret < 0) {
dev_err(&dev->dev, "unable to register port at index %d "
"(IO%lx MEM%llx IRQ%d): %d\n", i,
@@ -3073,7 +3085,7 @@ static struct platform_driver serial8250_isa_driver = {
static struct platform_device *serial8250_isa_devs;
/*
- * serial8250_register_port and serial8250_unregister_port allows for
+ * serial8250_register_8250_port and serial8250_unregister_port allows for
* 16x50 serial ports to be configured at run-time, to support PCMCIA
* modems and PCI multiport cards.
*/
@@ -3147,6 +3159,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
uart->port.regshift = up->port.regshift;
uart->port.iotype = up->port.iotype;
uart->port.flags = up->port.flags | UPF_BOOT_AUTOCONF;
+ uart->bugs = up->bugs;
uart->port.mapbase = up->port.mapbase;
uart->port.private_data = up->port.private_data;
if (up->port.dev)
@@ -3190,29 +3203,6 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
EXPORT_SYMBOL(serial8250_register_8250_port);
/**
- * serial8250_register_port - register a serial port
- * @port: serial port template
- *
- * Configure the serial port specified by the request. If the
- * port exists and is in use, it is hung up and unregistered
- * first.
- *
- * The port is then probed and if necessary the IRQ is autodetected
- * If this fails an error is returned.
- *
- * On success the port is ready to use and the line number is returned.
- */
-int serial8250_register_port(struct uart_port *port)
-{
- struct uart_8250_port up;
-
- memset(&up, 0, sizeof(up));
- memcpy(&up.port, port, sizeof(*port));
- return serial8250_register_8250_port(&up);
-}
-EXPORT_SYMBOL(serial8250_register_port);
-
-/**
* serial8250_unregister_port - remove a 16x50 serial port at runtime
* @line: serial line number
*
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index f9719d167c8d..c335b2b23a5f 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -78,6 +78,7 @@ struct serial8250_config {
#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
#define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */
#define UART_BUG_THRE (1 << 3) /* UART has buggy THRE reassertion */
+#define UART_BUG_PARITY (1 << 4) /* UART mishandles parity if FIFO enabled */
#define PROBE_RSA (1 << 0)
#define PROBE_ANY (~0)
diff --git a/drivers/tty/serial/8250/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c
index b0ce8c56f1a4..857498312a9a 100644
--- a/drivers/tty/serial/8250/8250_acorn.c
+++ b/drivers/tty/serial/8250/8250_acorn.c
@@ -43,7 +43,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct serial_card_info *info;
struct serial_card_type *type = id->data;
- struct uart_port port;
+ struct uart_8250_port uart;
unsigned long bus_addr;
unsigned int i;
@@ -62,19 +62,19 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
ecard_set_drvdata(ec, info);
- memset(&port, 0, sizeof(struct uart_port));
- port.irq = ec->irq;
- port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
- port.uartclk = type->uartclk;
- port.iotype = UPIO_MEM;
- port.regshift = 2;
- port.dev = &ec->dev;
+ memset(&uart, 0, sizeof(struct uart_8250_port));
+ uart.port.irq = ec->irq;
+ uart.port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ uart.port.uartclk = type->uartclk;
+ uart.port.iotype = UPIO_MEM;
+ uart.port.regshift = 2;
+ uart.port.dev = &ec->dev;
for (i = 0; i < info->num_ports; i ++) {
- port.membase = info->vaddr + type->offset[i];
- port.mapbase = bus_addr + type->offset[i];
+ uart.port.membase = info->vaddr + type->offset[i];
+ uart.port.mapbase = bus_addr + type->offset[i];
- info->ports[i] = serial8250_register_port(&port);
+ info->ports[i] = serial8250_register_8250_port(&uart);
}
return 0;
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index f574eef3075f..afb955fdef03 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -89,7 +89,7 @@ static int dw8250_handle_irq(struct uart_port *p)
static int __devinit dw8250_probe(struct platform_device *pdev)
{
- struct uart_port port = {};
+ struct uart_8250_port uart = {};
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
struct device_node *np = pdev->dev.of_node;
@@ -104,28 +104,28 @@ static int __devinit dw8250_probe(struct platform_device *pdev)
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- port.private_data = data;
-
- spin_lock_init(&port.lock);
- port.mapbase = regs->start;
- port.irq = irq->start;
- port.handle_irq = dw8250_handle_irq;
- port.type = PORT_8250;
- port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
+ uart.port.private_data = data;
+
+ spin_lock_init(&uart.port.lock);
+ uart.port.mapbase = regs->start;
+ uart.port.irq = irq->start;
+ uart.port.handle_irq = dw8250_handle_irq;
+ uart.port.type = PORT_8250;
+ uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
UPF_FIXED_PORT | UPF_FIXED_TYPE;
- port.dev = &pdev->dev;
+ uart.port.dev = &pdev->dev;
- port.iotype = UPIO_MEM;
- port.serial_in = dw8250_serial_in;
- port.serial_out = dw8250_serial_out;
+ uart.port.iotype = UPIO_MEM;
+ uart.port.serial_in = dw8250_serial_in;
+ uart.port.serial_out = dw8250_serial_out;
if (!of_property_read_u32(np, "reg-io-width", &val)) {
switch (val) {
case 1:
break;
case 4:
- port.iotype = UPIO_MEM32;
- port.serial_in = dw8250_serial_in32;
- port.serial_out = dw8250_serial_out32;
+ uart.port.iotype = UPIO_MEM32;
+ uart.port.serial_in = dw8250_serial_in32;
+ uart.port.serial_out = dw8250_serial_out32;
break;
default:
dev_err(&pdev->dev, "unsupported reg-io-width (%u)\n",
@@ -135,15 +135,15 @@ static int __devinit dw8250_probe(struct platform_device *pdev)
}
if (!of_property_read_u32(np, "reg-shift", &val))
- port.regshift = val;
+ uart.port.regshift = val;
if (of_property_read_u32(np, "clock-frequency", &val)) {
dev_err(&pdev->dev, "no clock-frequency property set\n");
return -EINVAL;
}
- port.uartclk = val;
+ uart.uart.port.uartclk = val;
- data->line = serial8250_register_port(&port);
+ data->line = serial8250_register_8250_port(&uart);
if (data->line < 0)
return data->line;
diff --git a/drivers/tty/serial/8250/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c
index d8c0ffbfa6e3..097dff9c08ad 100644
--- a/drivers/tty/serial/8250/8250_gsc.c
+++ b/drivers/tty/serial/8250/8250_gsc.c
@@ -26,7 +26,7 @@
static int __init serial_init_chip(struct parisc_device *dev)
{
- struct uart_port port;
+ struct uart_8250_port uart;
unsigned long address;
int err;
@@ -48,21 +48,21 @@ static int __init serial_init_chip(struct parisc_device *dev)
if (dev->id.sversion != 0x8d)
address += 0x800;
- memset(&port, 0, sizeof(port));
- port.iotype = UPIO_MEM;
+ memset(&uart, 0, sizeof(uart));
+ uart.port.iotype = UPIO_MEM;
/* 7.272727MHz on Lasi. Assumed the same for Dino, Wax and Timi. */
- port.uartclk = 7272727;
- port.mapbase = address;
- port.membase = ioremap_nocache(address, 16);
- port.irq = dev->irq;
- port.flags = UPF_BOOT_AUTOCONF;
- port.dev = &dev->dev;
-
- err = serial8250_register_port(&port);
+ uart.port.uartclk = 7272727;
+ uart.port.mapbase = address;
+ uart.port.membase = ioremap_nocache(address, 16);
+ uart.port.irq = dev->irq;
+ uart.port.flags = UPF_BOOT_AUTOCONF;
+ uart.port.dev = &dev->dev;
+
+ err = serial8250_register_8250_port(&uart);
if (err < 0) {
printk(KERN_WARNING
- "serial8250_register_port returned error %d\n", err);
- iounmap(port.membase);
+ "serial8250_register_8250_port returned error %d\n", err);
+ iounmap(uart.port.membase);
return err;
}
diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c
index c13438c93012..8f1dd2cc00a8 100644
--- a/drivers/tty/serial/8250/8250_hp300.c
+++ b/drivers/tty/serial/8250/8250_hp300.c
@@ -171,7 +171,7 @@ static int __devinit hpdca_init_one(struct dio_dev *d,
return 0;
}
#endif
- memset(&port, 0, sizeof(struct uart_port));
+ memset(&uart, 0, sizeof(uart));
/* Memory mapped I/O */
port.iotype = UPIO_MEM;
@@ -182,7 +182,7 @@ static int __devinit hpdca_init_one(struct dio_dev *d,
port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
port.regshift = 1;
port.dev = &d->dev;
- line = serial8250_register_port(&port);
+ line = serial8250_register_8250_port(&uart);
if (line < 0) {
printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
@@ -210,7 +210,7 @@ static int __init hp300_8250_init(void)
#ifdef CONFIG_HPAPCI
int line;
unsigned long base;
- struct uart_port uport;
+ struct uart_8250_port uart;
struct hp300_port *port;
int i;
#endif
@@ -248,26 +248,26 @@ static int __init hp300_8250_init(void)
if (!port)
return -ENOMEM;
- memset(&uport, 0, sizeof(struct uart_port));
+ memset(&uart, 0, sizeof(uart));
base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
/* Memory mapped I/O */
- uport.iotype = UPIO_MEM;
- uport.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \
+ uart.port.iotype = UPIO_MEM;
+ uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \
| UPF_BOOT_AUTOCONF;
/* XXX - no interrupt support yet */
- uport.irq = 0;
- uport.uartclk = HPAPCI_BAUD_BASE * 16;
- uport.mapbase = base;
- uport.membase = (char *)(base + DIO_VIRADDRBASE);
- uport.regshift = 2;
+ uart.port.irq = 0;
+ uart.port.uartclk = HPAPCI_BAUD_BASE * 16;
+ uart.port.mapbase = base;
+ uart.port.membase = (char *)(base + DIO_VIRADDRBASE);
+ uart.port.regshift = 2;
- line = serial8250_register_port(&uport);
+ line = serial8250_register_8250_port(&uart);
if (line < 0) {
printk(KERN_NOTICE "8250_hp300: register_serial() APCI"
- " %d irq %d failed\n", i, uport.irq);
+ " %d irq %d failed\n", i, uart.port.irq);
kfree(port);
continue;
}
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 28e7c7cce893..62e10fe747a8 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -44,7 +44,7 @@ struct pci_serial_quirk {
int (*init)(struct pci_dev *dev);
int (*setup)(struct serial_private *,
const struct pciserial_board *,
- struct uart_port *, int);
+ struct uart_8250_port *, int);
void (*exit)(struct pci_dev *dev);
};
@@ -59,7 +59,7 @@ struct serial_private {
};
static int pci_default_setup(struct serial_private*,
- const struct pciserial_board*, struct uart_port*, int);
+ const struct pciserial_board*, struct uart_8250_port *, int);
static void moan_device(const char *str, struct pci_dev *dev)
{
@@ -74,7 +74,7 @@ static void moan_device(const char *str, struct pci_dev *dev)
}
static int
-setup_port(struct serial_private *priv, struct uart_port *port,
+setup_port(struct serial_private *priv, struct uart_8250_port *port,
int bar, int offset, int regshift)
{
struct pci_dev *dev = priv->dev;
@@ -93,17 +93,17 @@ setup_port(struct serial_private *priv, struct uart_port *port,
if (!priv->remapped_bar[bar])
return -ENOMEM;
- port->iotype = UPIO_MEM;
- port->iobase = 0;
- port->mapbase = base + offset;
- port->membase = priv->remapped_bar[bar] + offset;
- port->regshift = regshift;
+ port->port.iotype = UPIO_MEM;
+ port->port.iobase = 0;
+ port->port.mapbase = base + offset;
+ port->port.membase = priv->remapped_bar[bar] + offset;
+ port->port.regshift = regshift;
} else {
- port->iotype = UPIO_PORT;
- port->iobase = base + offset;
- port->mapbase = 0;
- port->membase = NULL;
- port->regshift = 0;
+ port->port.iotype = UPIO_PORT;
+ port->port.iobase = base + offset;
+ port->port.mapbase = 0;
+ port->port.membase = NULL;
+ port->port.regshift = 0;
}
return 0;
}
@@ -113,7 +113,7 @@ setup_port(struct serial_private *priv, struct uart_port *port,
*/
static int addidata_apci7800_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar = 0, offset = board->first_offset;
bar = FL_GET_BASE(board->flags);
@@ -140,7 +140,7 @@ static int addidata_apci7800_setup(struct serial_private *priv,
*/
static int
afavlab_setup(struct serial_private *priv, const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -195,7 +195,7 @@ static int pci_hp_diva_init(struct pci_dev *dev)
static int
pci_hp_diva_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int offset = board->first_offset;
unsigned int bar = FL_GET_BASE(board->flags);
@@ -370,7 +370,7 @@ static void __devexit pci_ni8430_exit(struct pci_dev *dev)
/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
static int
sbs_setup(struct serial_private *priv, const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -525,7 +525,7 @@ static int pci_siig_init(struct pci_dev *dev)
static int pci_siig_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0;
@@ -619,7 +619,7 @@ static int pci_timedia_init(struct pci_dev *dev)
static int
pci_timedia_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar = 0, offset = board->first_offset;
@@ -653,7 +653,7 @@ pci_timedia_setup(struct serial_private *priv,
static int
titan_400l_800l_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -754,7 +754,7 @@ static int pci_ni8430_init(struct pci_dev *dev)
static int
pci_ni8430_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
void __iomem *p;
unsigned long base, len;
@@ -781,7 +781,7 @@ pci_ni8430_setup(struct serial_private *priv,
static int pci_netmos_9900_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar;
@@ -1032,10 +1032,17 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
return number_uarts;
}
-static int
-pci_default_setup(struct serial_private *priv,
+static int pci_asix_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_8250_port *port, int idx)
+{
+ port->bugs |= UART_BUG_PARITY;
+ return pci_default_setup(priv, board, port, idx);
+}
+
+static int pci_default_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar, offset = board->first_offset, maxnr;
@@ -1057,15 +1064,15 @@ pci_default_setup(struct serial_private *priv,
static int
ce4100_serial_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
int ret;
ret = setup_port(priv, port, 0, 0, board->reg_shift);
- port->iotype = UPIO_MEM32;
- port->type = PORT_XSCALE;
- port->flags = (port->flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
- port->regshift = 2;
+ port->port.iotype = UPIO_MEM32;
+ port->port.type = PORT_XSCALE;
+ port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
+ port->port.regshift = 2;
return ret;
}
@@ -1073,16 +1080,16 @@ ce4100_serial_setup(struct serial_private *priv,
static int
pci_omegapci_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
return setup_port(priv, port, 2, idx * 8, 0);
}
static int skip_tx_en_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
- port->flags |= UPF_NO_TXEN_TEST;
+ port->port.flags |= UPF_NO_TXEN_TEST;
printk(KERN_DEBUG "serial8250: skipping TxEn test for device "
"[%04x:%04x] subsystem [%04x:%04x]\n",
priv->dev->vendor,
@@ -1131,11 +1138,11 @@ static unsigned int kt_serial_in(struct uart_port *p, int offset)
static int kt_serial_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
- port->flags |= UPF_BUG_THRE;
- port->serial_in = kt_serial_in;
- port->handle_break = kt_handle_break;
+ port->port.flags |= UPF_BUG_THRE;
+ port->port.serial_in = kt_serial_in;
+ port->port.handle_break = kt_handle_break;
return skip_tx_en_setup(priv, board, port, idx);
}
@@ -1151,9 +1158,9 @@ static int pci_eg20t_init(struct pci_dev *dev)
static int
pci_xr17c154_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
- port->flags |= UPF_EXAR_EFR;
+ port->port.flags |= UPF_EXAR_EFR;
return pci_default_setup(priv, board, port, idx);
}
@@ -1187,6 +1194,7 @@ pci_xr17c154_setup(struct serial_private *priv,
#define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6
#define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001
#define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d
+#define PCI_VENDOR_ID_ASIX 0x9710
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
@@ -1726,7 +1734,17 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_omegapci_setup,
- },
+ },
+ /*
+ * ASIX devices with FIFO bug
+ */
+ {
+ .vendor = PCI_VENDOR_ID_ASIX,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_asix_setup,
+ },
/*
* Default "match everything" terminator entry
*/
@@ -1887,7 +1905,6 @@ enum pci_board_num_t {
pbn_panacom,
pbn_panacom2,
pbn_panacom4,
- pbn_exsys_4055,
pbn_plx_romulus,
pbn_oxsemi,
pbn_oxsemi_1_4000000,
@@ -2393,13 +2410,6 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.reg_shift = 7,
},
- [pbn_exsys_4055] = {
- .flags = FL_BASE2,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
-
/* I think this entry is broken - the first_offset looks wrong --rmk */
[pbn_plx_romulus] = {
.flags = FL_BASE2,
@@ -2728,7 +2738,7 @@ serial_pci_matches(const struct pciserial_board *board,
struct serial_private *
pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
{
- struct uart_port serial_port;
+ struct uart_8250_port uart;
struct serial_private *priv;
struct pci_serial_quirk *quirk;
int rc, nr_ports, i;
@@ -2768,22 +2778,22 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
priv->dev = dev;
priv->quirk = quirk;
- memset(&serial_port, 0, sizeof(struct uart_port));
- serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
- serial_port.uartclk = board->base_baud * 16;
- serial_port.irq = get_pci_irq(dev, board);
- serial_port.dev = &dev->dev;
+ memset(&uart, 0, sizeof(uart));
+ uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ uart.port.uartclk = board->base_baud * 16;
+ uart.port.irq = get_pci_irq(dev, board);
+ uart.port.dev = &dev->dev;
for (i = 0; i < nr_ports; i++) {
- if (quirk->setup(priv, board, &serial_port, i))
+ if (quirk->setup(priv, board, &uart, i))
break;
#ifdef SERIAL_DEBUG_PCI
printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n",
- serial_port.iobase, serial_port.irq, serial_port.iotype);
+ uart.port.iobase, uart.port.irq, uart.port.iotype);
#endif
- priv->line[i] = serial8250_register_port(&serial_port);
+ priv->line[i] = serial8250_register_8250_port(&uart);
if (priv->line[i] < 0) {
printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);
break;
@@ -3193,7 +3203,7 @@ static struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
PCI_SUBVENDOR_ID_EXSYS,
PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0,
- pbn_exsys_4055 },
+ pbn_b2_4_115200 },
/*
* Megawolf Romulus PCI Serial Card, from Mike Hudson
* (Exoray@isys.ca)
diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
index a2f236510ff1..fde5aa60d51e 100644
--- a/drivers/tty/serial/8250/8250_pnp.c
+++ b/drivers/tty/serial/8250/8250_pnp.c
@@ -424,7 +424,7 @@ static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags)
static int __devinit
serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
{
- struct uart_port port;
+ struct uart_8250_port uart;
int ret, line, flags = dev_id->driver_data;
if (flags & UNKNOWN_DEV) {
@@ -433,32 +433,32 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
return ret;
}
- memset(&port, 0, sizeof(struct uart_port));
+ memset(&uart, 0, sizeof(uart));
if (pnp_irq_valid(dev, 0))
- port.irq = pnp_irq(dev, 0);
+ uart.port.irq = pnp_irq(dev, 0);
if (pnp_port_valid(dev, 0)) {
- port.iobase = pnp_port_start(dev, 0);
- port.iotype = UPIO_PORT;
+ uart.port.iobase = pnp_port_start(dev, 0);
+ uart.port.iotype = UPIO_PORT;
} else if (pnp_mem_valid(dev, 0)) {
- port.mapbase = pnp_mem_start(dev, 0);
- port.iotype = UPIO_MEM;
- port.flags = UPF_IOREMAP;
+ uart.port.mapbase = pnp_mem_start(dev, 0);
+ uart.port.iotype = UPIO_MEM;
+ uart.port.flags = UPF_IOREMAP;
} else
return -ENODEV;
#ifdef SERIAL_DEBUG_PNP
printk(KERN_DEBUG
"Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n",
- port.iobase, port.mapbase, port.irq, port.iotype);
+ uart.port.iobase, uart.port.mapbase, uart.port.irq, uart.port.iotype);
#endif
- port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
+ uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
- port.flags |= UPF_SHARE_IRQ;
- port.uartclk = 1843200;
- port.dev = &dev->dev;
+ uart.port.flags |= UPF_SHARE_IRQ;
+ uart.port.uartclk = 1843200;
+ uart.port.dev = &dev->dev;
- line = serial8250_register_port(&port);
+ line = serial8250_register_8250_port(&uart);
if (line < 0)
return -ENODEV;
diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c
index 29b695d041ec..b7d48b346393 100644
--- a/drivers/tty/serial/8250/serial_cs.c
+++ b/drivers/tty/serial/8250/serial_cs.c
@@ -73,7 +73,7 @@ struct serial_quirk {
unsigned int prodid;
int multi; /* 1 = multifunction, > 1 = # ports */
void (*config)(struct pcmcia_device *);
- void (*setup)(struct pcmcia_device *, struct uart_port *);
+ void (*setup)(struct pcmcia_device *, struct uart_8250_port *);
void (*wakeup)(struct pcmcia_device *);
int (*post)(struct pcmcia_device *);
};
@@ -105,9 +105,9 @@ struct serial_cfg_mem {
* Elan VPU16551 UART with 14.7456MHz oscillator
* manfid 0x015D, 0x4C45
*/
-static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_port *port)
+static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_8250_port *uart)
{
- port->uartclk = 14745600;
+ uart->port.uartclk = 14745600;
}
static int quirk_post_ibm(struct pcmcia_device *link)
@@ -343,25 +343,25 @@ static void serial_detach(struct pcmcia_device *link)
static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
unsigned int iobase, int irq)
{
- struct uart_port port;
+ struct uart_8250_port uart;
int line;
- memset(&port, 0, sizeof (struct uart_port));
- port.iobase = iobase;
- port.irq = irq;
- port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
- port.uartclk = 1843200;
- port.dev = &handle->dev;
+ memset(&uart, 0, sizeof(uart));
+ uart.port.iobase = iobase;
+ uart.port.irq = irq;
+ uart.port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
+ uart.port.uartclk = 1843200;
+ uart.port.dev = &handle->dev;
if (buggy_uart)
- port.flags |= UPF_BUGGY_UART;
+ uart.port.flags |= UPF_BUGGY_UART;
if (info->quirk && info->quirk->setup)
- info->quirk->setup(handle, &port);
+ info->quirk->setup(handle, &uart);
- line = serial8250_register_port(&port);
+ line = serial8250_register_8250_port(&uart);
if (line < 0) {
- printk(KERN_NOTICE "serial_cs: serial8250_register_port() at "
- "0x%04lx, irq %d failed\n", (u_long)iobase, irq);
+ pr_err("serial_cs: serial8250_register_8250_port() at 0x%04lx, irq %d failed\n",
+ (unsigned long)iobase, irq);
return -EINVAL;
}
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 070b442c1f81..00207865ec55 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -704,6 +704,25 @@ config SERIAL_PNX8XXX_CONSOLE
If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330
and you want to use serial console, say Y. Otherwise, say N.
+config SERIAL_HS_LPC32XX
+ tristate "LPC32XX high speed serial port support"
+ depends on ARCH_LPC32XX && OF
+ select SERIAL_CORE
+ help
+ Support for the LPC32XX high speed serial ports (up to 900kbps).
+ Those are UARTs completely different from the Standard UARTs on the
+ LPC32XX SoC.
+ Choose M or Y here to build this driver.
+
+config SERIAL_HS_LPC32XX_CONSOLE
+ bool "Enable LPC32XX high speed UART serial console"
+ depends on SERIAL_HS_LPC32XX
+ select SERIAL_CORE_CONSOLE
+ help
+ If you would like to be able to use one of the high speed serial
+ ports on the LPC32XX as the console, you can do so by answering
+ Y to this option.
+
config SERIAL_CORE
tristate
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 7257c5d898ae..8a5df3804e5f 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_SERIAL_MUX) += mux.o
obj-$(CONFIG_SERIAL_68328) += 68328serial.o
obj-$(CONFIG_SERIAL_MCF) += mcf.o
obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o
+obj-$(CONFIG_SERIAL_HS_LPC32XX) += lpc32xx_hs.o
obj-$(CONFIG_SERIAL_DZ) += dz.o
obj-$(CONFIG_SERIAL_ZS) += zs.o
obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index c17923ec6e95..b81cc31f2657 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1215,14 +1215,14 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
return IRQ_RETVAL(handled);
}
-static unsigned int pl01x_tx_empty(struct uart_port *port)
+static unsigned int pl011_tx_empty(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
unsigned int status = readw(uap->port.membase + UART01x_FR);
return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
}
-static unsigned int pl01x_get_mctrl(struct uart_port *port)
+static unsigned int pl011_get_mctrl(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
unsigned int result = 0;
@@ -1285,7 +1285,7 @@ static void pl011_break_ctl(struct uart_port *port, int break_state)
}
#ifdef CONFIG_CONSOLE_POLL
-static int pl010_get_poll_char(struct uart_port *port)
+static int pl011_get_poll_char(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
unsigned int status;
@@ -1297,7 +1297,7 @@ static int pl010_get_poll_char(struct uart_port *port)
return readw(uap->port.membase + UART01x_DR);
}
-static void pl010_put_poll_char(struct uart_port *port,
+static void pl011_put_poll_char(struct uart_port *port,
unsigned char ch)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
@@ -1637,7 +1637,7 @@ static const char *pl011_type(struct uart_port *port)
/*
* Release the memory region(s) being used by 'port'
*/
-static void pl010_release_port(struct uart_port *port)
+static void pl011_release_port(struct uart_port *port)
{
release_mem_region(port->mapbase, SZ_4K);
}
@@ -1645,7 +1645,7 @@ static void pl010_release_port(struct uart_port *port)
/*
* Request the memory region(s) being used by 'port'
*/
-static int pl010_request_port(struct uart_port *port)
+static int pl011_request_port(struct uart_port *port)
{
return request_mem_region(port->mapbase, SZ_4K, "uart-pl011")
!= NULL ? 0 : -EBUSY;
@@ -1654,18 +1654,18 @@ static int pl010_request_port(struct uart_port *port)
/*
* Configure/autoconfigure the port.
*/
-static void pl010_config_port(struct uart_port *port, int flags)
+static void pl011_config_port(struct uart_port *port, int flags)
{
if (flags & UART_CONFIG_TYPE) {
port->type = PORT_AMBA;
- pl010_request_port(port);
+ pl011_request_port(port);
}
}
/*
* verify the new serial_struct (for TIOCSSERIAL).
*/
-static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
+static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser)
{
int ret = 0;
if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
@@ -1678,9 +1678,9 @@ static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
}
static struct uart_ops amba_pl011_pops = {
- .tx_empty = pl01x_tx_empty,
+ .tx_empty = pl011_tx_empty,
.set_mctrl = pl011_set_mctrl,
- .get_mctrl = pl01x_get_mctrl,
+ .get_mctrl = pl011_get_mctrl,
.stop_tx = pl011_stop_tx,
.start_tx = pl011_start_tx,
.stop_rx = pl011_stop_rx,
@@ -1691,13 +1691,13 @@ static struct uart_ops amba_pl011_pops = {
.flush_buffer = pl011_dma_flush_buffer,
.set_termios = pl011_set_termios,
.type = pl011_type,
- .release_port = pl010_release_port,
- .request_port = pl010_request_port,
- .config_port = pl010_config_port,
- .verify_port = pl010_verify_port,
+ .release_port = pl011_release_port,
+ .request_port = pl011_request_port,
+ .config_port = pl011_config_port,
+ .verify_port = pl011_verify_port,
#ifdef CONFIG_CONSOLE_POLL
- .poll_get_char = pl010_get_poll_char,
- .poll_put_char = pl010_put_poll_char,
+ .poll_get_char = pl011_get_poll_char,
+ .poll_put_char = pl011_put_poll_char,
#endif
};
diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c
index 80b6b1b1f725..7264d4d26717 100644
--- a/drivers/tty/serial/crisv10.c
+++ b/drivers/tty/serial/crisv10.c
@@ -3976,7 +3976,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
- wait_event_interruptible_tty(info->close_wait,
+ wait_event_interruptible_tty(tty, info->close_wait,
!(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
if (info->flags & ASYNC_HUP_NOTIFY)
@@ -4052,9 +4052,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
printk("block_til_ready blocking: ttyS%d, count = %d\n",
info->line, info->count);
#endif
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&info->open_wait, &wait);
@@ -4115,7 +4115,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
- wait_event_interruptible_tty(info->close_wait,
+ wait_event_interruptible_tty(tty, info->close_wait,
!(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
return ((info->flags & ASYNC_HUP_NOTIFY) ?
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 4ef747307ecb..0af4eec8c7b1 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -207,7 +207,7 @@ struct imx_port {
unsigned short trcv_delay; /* transceiver delay */
struct clk *clk_ipg;
struct clk *clk_per;
- struct imx_uart_data *devdata;
+ const struct imx_uart_data *devdata;
};
struct imx_port_ucrs {
diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
new file mode 100644
index 000000000000..ba3af3bf6d43
--- /dev/null
+++ b/drivers/tty/serial/lpc32xx_hs.c
@@ -0,0 +1,823 @@
+/*
+ * High Speed Serial Ports on NXP LPC32xx SoC
+ *
+ * Authors: Kevin Wells <kevin.wells@nxp.com>
+ * Roland Stigge <stigge@antcom.de>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ * Copyright (C) 2012 Roland Stigge
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/nmi.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <mach/platform.h>
+#include <mach/hardware.h>
+
+/*
+ * High Speed UART register offsets
+ */
+#define LPC32XX_HSUART_FIFO(x) ((x) + 0x00)
+#define LPC32XX_HSUART_LEVEL(x) ((x) + 0x04)
+#define LPC32XX_HSUART_IIR(x) ((x) + 0x08)
+#define LPC32XX_HSUART_CTRL(x) ((x) + 0x0C)
+#define LPC32XX_HSUART_RATE(x) ((x) + 0x10)
+
+#define LPC32XX_HSU_BREAK_DATA (1 << 10)
+#define LPC32XX_HSU_ERROR_DATA (1 << 9)
+#define LPC32XX_HSU_RX_EMPTY (1 << 8)
+
+#define LPC32XX_HSU_TX_LEV(n) (((n) >> 8) & 0xFF)
+#define LPC32XX_HSU_RX_LEV(n) ((n) & 0xFF)
+
+#define LPC32XX_HSU_TX_INT_SET (1 << 6)
+#define LPC32XX_HSU_RX_OE_INT (1 << 5)
+#define LPC32XX_HSU_BRK_INT (1 << 4)
+#define LPC32XX_HSU_FE_INT (1 << 3)
+#define LPC32XX_HSU_RX_TIMEOUT_INT (1 << 2)
+#define LPC32XX_HSU_RX_TRIG_INT (1 << 1)
+#define LPC32XX_HSU_TX_INT (1 << 0)
+
+#define LPC32XX_HSU_HRTS_INV (1 << 21)
+#define LPC32XX_HSU_HRTS_TRIG_8B (0x0 << 19)
+#define LPC32XX_HSU_HRTS_TRIG_16B (0x1 << 19)
+#define LPC32XX_HSU_HRTS_TRIG_32B (0x2 << 19)
+#define LPC32XX_HSU_HRTS_TRIG_48B (0x3 << 19)
+#define LPC32XX_HSU_HRTS_EN (1 << 18)
+#define LPC32XX_HSU_TMO_DISABLED (0x0 << 16)
+#define LPC32XX_HSU_TMO_INACT_4B (0x1 << 16)
+#define LPC32XX_HSU_TMO_INACT_8B (0x2 << 16)
+#define LPC32XX_HSU_TMO_INACT_16B (0x3 << 16)
+#define LPC32XX_HSU_HCTS_INV (1 << 15)
+#define LPC32XX_HSU_HCTS_EN (1 << 14)
+#define LPC32XX_HSU_OFFSET(n) ((n) << 9)
+#define LPC32XX_HSU_BREAK (1 << 8)
+#define LPC32XX_HSU_ERR_INT_EN (1 << 7)
+#define LPC32XX_HSU_RX_INT_EN (1 << 6)
+#define LPC32XX_HSU_TX_INT_EN (1 << 5)
+#define LPC32XX_HSU_RX_TL1B (0x0 << 2)
+#define LPC32XX_HSU_RX_TL4B (0x1 << 2)
+#define LPC32XX_HSU_RX_TL8B (0x2 << 2)
+#define LPC32XX_HSU_RX_TL16B (0x3 << 2)
+#define LPC32XX_HSU_RX_TL32B (0x4 << 2)
+#define LPC32XX_HSU_RX_TL48B (0x5 << 2)
+#define LPC32XX_HSU_TX_TLEMPTY (0x0 << 0)
+#define LPC32XX_HSU_TX_TL0B (0x0 << 0)
+#define LPC32XX_HSU_TX_TL4B (0x1 << 0)
+#define LPC32XX_HSU_TX_TL8B (0x2 << 0)
+#define LPC32XX_HSU_TX_TL16B (0x3 << 0)
+
+#define MODNAME "lpc32xx_hsuart"
+
+struct lpc32xx_hsuart_port {
+ struct uart_port port;
+};
+
+#define FIFO_READ_LIMIT 128
+#define MAX_PORTS 3
+#define LPC32XX_TTY_NAME "ttyTX"
+static struct lpc32xx_hsuart_port lpc32xx_hs_ports[MAX_PORTS];
+
+#ifdef CONFIG_SERIAL_HS_LPC32XX_CONSOLE
+static void wait_for_xmit_empty(struct uart_port *port)
+{
+ unsigned int timeout = 10000;
+
+ do {
+ if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(
+ port->membase))) == 0)
+ break;
+ if (--timeout == 0)
+ break;
+ udelay(1);
+ } while (1);
+}
+
+static void wait_for_xmit_ready(struct uart_port *port)
+{
+ unsigned int timeout = 10000;
+
+ while (1) {
+ if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(
+ port->membase))) < 32)
+ break;
+ if (--timeout == 0)
+ break;
+ udelay(1);
+ }
+}
+
+static void lpc32xx_hsuart_console_putchar(struct uart_port *port, int ch)
+{
+ wait_for_xmit_ready(port);
+ writel((u32)ch, LPC32XX_HSUART_FIFO(port->membase));
+}
+
+static void lpc32xx_hsuart_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ struct lpc32xx_hsuart_port *up = &lpc32xx_hs_ports[co->index];
+ unsigned long flags;
+ int locked = 1;
+
+ touch_nmi_watchdog();
+ local_irq_save(flags);
+ if (up->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+ locked = spin_trylock(&up->port.lock);
+ else
+ spin_lock(&up->port.lock);
+
+ uart_console_write(&up->port, s, count, lpc32xx_hsuart_console_putchar);
+ wait_for_xmit_empty(&up->port);
+
+ if (locked)
+ spin_unlock(&up->port.lock);
+ local_irq_restore(flags);
+}
+
+static int __init lpc32xx_hsuart_console_setup(struct console *co,
+ char *options)
+{
+ struct uart_port *port;
+ int baud = 115200;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if (co->index >= MAX_PORTS)
+ co->index = 0;
+
+ port = &lpc32xx_hs_ports[co->index].port;
+ if (!port->membase)
+ return -ENODEV;
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver lpc32xx_hsuart_reg;
+static struct console lpc32xx_hsuart_console = {
+ .name = LPC32XX_TTY_NAME,
+ .write = lpc32xx_hsuart_console_write,
+ .device = uart_console_device,
+ .setup = lpc32xx_hsuart_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &lpc32xx_hsuart_reg,
+};
+
+static int __init lpc32xx_hsuart_console_init(void)
+{
+ register_console(&lpc32xx_hsuart_console);
+ return 0;
+}
+console_initcall(lpc32xx_hsuart_console_init);
+
+#define LPC32XX_HSUART_CONSOLE (&lpc32xx_hsuart_console)
+#else
+#define LPC32XX_HSUART_CONSOLE NULL
+#endif
+
+static struct uart_driver lpc32xx_hs_reg = {
+ .owner = THIS_MODULE,
+ .driver_name = MODNAME,
+ .dev_name = LPC32XX_TTY_NAME,
+ .nr = MAX_PORTS,
+ .cons = LPC32XX_HSUART_CONSOLE,
+};
+static int uarts_registered;
+
+static unsigned int __serial_get_clock_div(unsigned long uartclk,
+ unsigned long rate)
+{
+ u32 div, goodrate, hsu_rate, l_hsu_rate, comprate;
+ u32 rate_diff;
+
+ /* Find the closest divider to get the desired clock rate */
+ div = uartclk / rate;
+ goodrate = hsu_rate = (div / 14) - 1;
+ if (hsu_rate != 0)
+ hsu_rate--;
+
+ /* Tweak divider */
+ l_hsu_rate = hsu_rate + 3;
+ rate_diff = 0xFFFFFFFF;
+
+ while (hsu_rate < l_hsu_rate) {
+ comprate = uartclk / ((hsu_rate + 1) * 14);
+ if (abs(comprate - rate) < rate_diff) {
+ goodrate = hsu_rate;
+ rate_diff = abs(comprate - rate);
+ }
+
+ hsu_rate++;
+ }
+ if (hsu_rate > 0xFF)
+ hsu_rate = 0xFF;
+
+ return goodrate;
+}
+
+static void __serial_uart_flush(struct uart_port *port)
+{
+ u32 tmp;
+ int cnt = 0;
+
+ while ((readl(LPC32XX_HSUART_LEVEL(port->membase)) > 0) &&
+ (cnt++ < FIFO_READ_LIMIT))
+ tmp = readl(LPC32XX_HSUART_FIFO(port->membase));
+}
+
+static void __serial_lpc32xx_rx(struct uart_port *port)
+{
+ unsigned int tmp, flag;
+ struct tty_struct *tty = tty_port_tty_get(&port->state->port);
+
+ if (!tty) {
+ /* Discard data: no tty available */
+ while (!(readl(LPC32XX_HSUART_FIFO(port->membase)) &
+ LPC32XX_HSU_RX_EMPTY))
+ ;
+
+ return;
+ }
+
+ /* Read data from FIFO and push into terminal */
+ tmp = readl(LPC32XX_HSUART_FIFO(port->membase));
+ while (!(tmp & LPC32XX_HSU_RX_EMPTY)) {
+ flag = TTY_NORMAL;
+ port->icount.rx++;
+
+ if (tmp & LPC32XX_HSU_ERROR_DATA) {
+ /* Framing error */
+ writel(LPC32XX_HSU_FE_INT,
+ LPC32XX_HSUART_IIR(port->membase));
+ port->icount.frame++;
+ flag = TTY_FRAME;
+ tty_insert_flip_char(tty, 0, TTY_FRAME);
+ }
+
+ tty_insert_flip_char(tty, (tmp & 0xFF), flag);
+
+ tmp = readl(LPC32XX_HSUART_FIFO(port->membase));
+ }
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
+}
+
+static void __serial_lpc32xx_tx(struct uart_port *port)
+{
+ struct circ_buf *xmit = &port->state->xmit;
+ unsigned int tmp;
+
+ if (port->x_char) {
+ writel((u32)port->x_char, LPC32XX_HSUART_FIFO(port->membase));
+ port->icount.tx++;
+ port->x_char = 0;
+ return;
+ }
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port))
+ goto exit_tx;
+
+ /* Transfer data */
+ while (LPC32XX_HSU_TX_LEV(readl(
+ LPC32XX_HSUART_LEVEL(port->membase))) < 64) {
+ writel((u32) xmit->buf[xmit->tail],
+ LPC32XX_HSUART_FIFO(port->membase));
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ if (uart_circ_empty(xmit))
+ break;
+ }
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+exit_tx:
+ if (uart_circ_empty(xmit)) {
+ tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+ tmp &= ~LPC32XX_HSU_TX_INT_EN;
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+ }
+}
+
+static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id)
+{
+ struct uart_port *port = dev_id;
+ struct tty_struct *tty = tty_port_tty_get(&port->state->port);
+ u32 status;
+
+ spin_lock(&port->lock);
+
+ /* Read UART status and clear latched interrupts */
+ status = readl(LPC32XX_HSUART_IIR(port->membase));
+
+ if (status & LPC32XX_HSU_BRK_INT) {
+ /* Break received */
+ writel(LPC32XX_HSU_BRK_INT, LPC32XX_HSUART_IIR(port->membase));
+ port->icount.brk++;
+ uart_handle_break(port);
+ }
+
+ /* Framing error */
+ if (status & LPC32XX_HSU_FE_INT)
+ writel(LPC32XX_HSU_FE_INT, LPC32XX_HSUART_IIR(port->membase));
+
+ if (status & LPC32XX_HSU_RX_OE_INT) {
+ /* Receive FIFO overrun */
+ writel(LPC32XX_HSU_RX_OE_INT,
+ LPC32XX_HSUART_IIR(port->membase));
+ port->icount.overrun++;
+ if (tty) {
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ tty_schedule_flip(tty);
+ }
+ }
+
+ /* Data received? */
+ if (status & (LPC32XX_HSU_RX_TIMEOUT_INT | LPC32XX_HSU_RX_TRIG_INT)) {
+ __serial_lpc32xx_rx(port);
+ if (tty)
+ tty_flip_buffer_push(tty);
+ }
+
+ /* Transmit data request? */
+ if ((status & LPC32XX_HSU_TX_INT) && (!uart_tx_stopped(port))) {
+ writel(LPC32XX_HSU_TX_INT, LPC32XX_HSUART_IIR(port->membase));
+ __serial_lpc32xx_tx(port);
+ }
+
+ spin_unlock(&port->lock);
+ tty_kref_put(tty);
+
+ return IRQ_HANDLED;
+}
+
+/* port->lock is not held. */
+static unsigned int serial_lpc32xx_tx_empty(struct uart_port *port)
+{
+ unsigned int ret = 0;
+
+ if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(port->membase))) == 0)
+ ret = TIOCSER_TEMT;
+
+ return ret;
+}
+
+/* port->lock held by caller. */
+static void serial_lpc32xx_set_mctrl(struct uart_port *port,
+ unsigned int mctrl)
+{
+ /* No signals are supported on HS UARTs */
+}
+
+/* port->lock is held by caller and interrupts are disabled. */
+static unsigned int serial_lpc32xx_get_mctrl(struct uart_port *port)
+{
+ /* No signals are supported on HS UARTs */
+ return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+/* port->lock held by caller. */
+static void serial_lpc32xx_stop_tx(struct uart_port *port)
+{
+ u32 tmp;
+
+ tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+ tmp &= ~LPC32XX_HSU_TX_INT_EN;
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+}
+
+/* port->lock held by caller. */
+static void serial_lpc32xx_start_tx(struct uart_port *port)
+{
+ u32 tmp;
+
+ __serial_lpc32xx_tx(port);
+ tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+ tmp |= LPC32XX_HSU_TX_INT_EN;
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+}
+
+/* port->lock held by caller. */
+static void serial_lpc32xx_stop_rx(struct uart_port *port)
+{
+ u32 tmp;
+
+ tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+ tmp &= ~(LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN);
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+
+ writel((LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT |
+ LPC32XX_HSU_FE_INT), LPC32XX_HSUART_IIR(port->membase));
+}
+
+/* port->lock held by caller. */
+static void serial_lpc32xx_enable_ms(struct uart_port *port)
+{
+ /* Modem status is not supported */
+}
+
+/* port->lock is not held. */
+static void serial_lpc32xx_break_ctl(struct uart_port *port,
+ int break_state)
+{
+ unsigned long flags;
+ u32 tmp;
+
+ spin_lock_irqsave(&port->lock, flags);
+ tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+ if (break_state != 0)
+ tmp |= LPC32XX_HSU_BREAK;
+ else
+ tmp &= ~LPC32XX_HSU_BREAK;
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* LPC3250 Errata HSUART.1: Hang workaround via loopback mode on inactivity */
+static void lpc32xx_loopback_set(resource_size_t mapbase, int state)
+{
+ int bit;
+ u32 tmp;
+
+ switch (mapbase) {
+ case LPC32XX_HS_UART1_BASE:
+ bit = 0;
+ break;
+ case LPC32XX_HS_UART2_BASE:
+ bit = 1;
+ break;
+ case LPC32XX_HS_UART7_BASE:
+ bit = 6;
+ break;
+ default:
+ WARN(1, "lpc32xx_hs: Warning: Unknown port at %08x\n", mapbase);
+ return;
+ }
+
+ tmp = readl(LPC32XX_UARTCTL_CLOOP);
+ if (state)
+ tmp |= (1 << bit);
+ else
+ tmp &= ~(1 << bit);
+ writel(tmp, LPC32XX_UARTCTL_CLOOP);
+}
+
+/* port->lock is not held. */
+static int serial_lpc32xx_startup(struct uart_port *port)
+{
+ int retval;
+ unsigned long flags;
+ u32 tmp;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ __serial_uart_flush(port);
+
+ writel((LPC32XX_HSU_TX_INT | LPC32XX_HSU_FE_INT |
+ LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT),
+ LPC32XX_HSUART_IIR(port->membase));
+
+ writel(0xFF, LPC32XX_HSUART_RATE(port->membase));
+
+ /*
+ * Set receiver timeout, HSU offset of 20, no break, no interrupts,
+ * and default FIFO trigger levels
+ */
+ tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B |
+ LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B;
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+
+ lpc32xx_loopback_set(port->mapbase, 0); /* get out of loopback mode */
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ retval = request_irq(port->irq, serial_lpc32xx_interrupt,
+ 0, MODNAME, port);
+ if (!retval)
+ writel((tmp | LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN),
+ LPC32XX_HSUART_CTRL(port->membase));
+
+ return retval;
+}
+
+/* port->lock is not held. */
+static void serial_lpc32xx_shutdown(struct uart_port *port)
+{
+ u32 tmp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B |
+ LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B;
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+
+ lpc32xx_loopback_set(port->mapbase, 1); /* go to loopback mode */
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ free_irq(port->irq, port);
+}
+
+/* port->lock is not held. */
+static void serial_lpc32xx_set_termios(struct uart_port *port,
+ struct ktermios *termios,
+ struct ktermios *old)
+{
+ unsigned long flags;
+ unsigned int baud, quot;
+ u32 tmp;
+
+ /* Always 8-bit, no parity, 1 stop bit */
+ termios->c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD);
+ termios->c_cflag |= CS8;
+
+ termios->c_cflag &= ~(HUPCL | CMSPAR | CLOCAL | CRTSCTS);
+
+ baud = uart_get_baud_rate(port, termios, old, 0,
+ port->uartclk / 14);
+
+ quot = __serial_get_clock_div(port->uartclk, baud);
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* Ignore characters? */
+ tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+ if ((termios->c_cflag & CREAD) == 0)
+ tmp &= ~(LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN);
+ else
+ tmp |= LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN;
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+
+ writel(quot, LPC32XX_HSUART_RATE(port->membase));
+
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ /* Don't rewrite B0 */
+ if (tty_termios_baud_rate(termios))
+ tty_termios_encode_baud_rate(termios, baud, baud);
+}
+
+static const char *serial_lpc32xx_type(struct uart_port *port)
+{
+ return MODNAME;
+}
+
+static void serial_lpc32xx_release_port(struct uart_port *port)
+{
+ if ((port->iotype == UPIO_MEM32) && (port->mapbase)) {
+ if (port->flags & UPF_IOREMAP) {
+ iounmap(port->membase);
+ port->membase = NULL;
+ }
+
+ release_mem_region(port->mapbase, SZ_4K);
+ }
+}
+
+static int serial_lpc32xx_request_port(struct uart_port *port)
+{
+ int ret = -ENODEV;
+
+ if ((port->iotype == UPIO_MEM32) && (port->mapbase)) {
+ ret = 0;
+
+ if (!request_mem_region(port->mapbase, SZ_4K, MODNAME))
+ ret = -EBUSY;
+ else if (port->flags & UPF_IOREMAP) {
+ port->membase = ioremap(port->mapbase, SZ_4K);
+ if (!port->membase) {
+ release_mem_region(port->mapbase, SZ_4K);
+ ret = -ENOMEM;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static void serial_lpc32xx_config_port(struct uart_port *port, int uflags)
+{
+ int ret;
+
+ ret = serial_lpc32xx_request_port(port);
+ if (ret < 0)
+ return;
+ port->type = PORT_UART00;
+ port->fifosize = 64;
+
+ __serial_uart_flush(port);
+
+ writel((LPC32XX_HSU_TX_INT | LPC32XX_HSU_FE_INT |
+ LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT),
+ LPC32XX_HSUART_IIR(port->membase));
+
+ writel(0xFF, LPC32XX_HSUART_RATE(port->membase));
+
+ /* Set receiver timeout, HSU offset of 20, no break, no interrupts,
+ and default FIFO trigger levels */
+ writel(LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B |
+ LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B,
+ LPC32XX_HSUART_CTRL(port->membase));
+}
+
+static int serial_lpc32xx_verify_port(struct uart_port *port,
+ struct serial_struct *ser)
+{
+ int ret = 0;
+
+ if (ser->type != PORT_UART00)
+ ret = -EINVAL;
+
+ return ret;
+}
+
+static struct uart_ops serial_lpc32xx_pops = {
+ .tx_empty = serial_lpc32xx_tx_empty,
+ .set_mctrl = serial_lpc32xx_set_mctrl,
+ .get_mctrl = serial_lpc32xx_get_mctrl,
+ .stop_tx = serial_lpc32xx_stop_tx,
+ .start_tx = serial_lpc32xx_start_tx,
+ .stop_rx = serial_lpc32xx_stop_rx,
+ .enable_ms = serial_lpc32xx_enable_ms,
+ .break_ctl = serial_lpc32xx_break_ctl,
+ .startup = serial_lpc32xx_startup,
+ .shutdown = serial_lpc32xx_shutdown,
+ .set_termios = serial_lpc32xx_set_termios,
+ .type = serial_lpc32xx_type,
+ .release_port = serial_lpc32xx_release_port,
+ .request_port = serial_lpc32xx_request_port,
+ .config_port = serial_lpc32xx_config_port,
+ .verify_port = serial_lpc32xx_verify_port,
+};
+
+/*
+ * Register a set of serial devices attached to a platform device
+ */
+static int __devinit serial_hs_lpc32xx_probe(struct platform_device *pdev)
+{
+ struct lpc32xx_hsuart_port *p = &lpc32xx_hs_ports[uarts_registered];
+ int ret = 0;
+ struct resource *res;
+
+ if (uarts_registered >= MAX_PORTS) {
+ dev_err(&pdev->dev,
+ "Error: Number of possible ports exceeded (%d)!\n",
+ uarts_registered + 1);
+ return -ENXIO;
+ }
+
+ memset(p, 0, sizeof(*p));
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev,
+ "Error getting mem resource for HS UART port %d\n",
+ uarts_registered);
+ return -ENXIO;
+ }
+ p->port.mapbase = res->start;
+ p->port.membase = NULL;
+
+ p->port.irq = platform_get_irq(pdev, 0);
+ if (p->port.irq < 0) {
+ dev_err(&pdev->dev, "Error getting irq for HS UART port %d\n",
+ uarts_registered);
+ return p->port.irq;
+ }
+
+ p->port.iotype = UPIO_MEM32;
+ p->port.uartclk = LPC32XX_MAIN_OSC_FREQ;
+ p->port.regshift = 2;
+ p->port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP;
+ p->port.dev = &pdev->dev;
+ p->port.ops = &serial_lpc32xx_pops;
+ p->port.line = uarts_registered++;
+ spin_lock_init(&p->port.lock);
+
+ /* send port to loopback mode by default */
+ lpc32xx_loopback_set(p->port.mapbase, 1);
+
+ ret = uart_add_one_port(&lpc32xx_hs_reg, &p->port);
+
+ platform_set_drvdata(pdev, p);
+
+ return ret;
+}
+
+/*
+ * Remove serial ports registered against a platform device.
+ */
+static int __devexit serial_hs_lpc32xx_remove(struct platform_device *pdev)
+{
+ struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);
+
+ uart_remove_one_port(&lpc32xx_hs_reg, &p->port);
+
+ return 0;
+}
+
+
+#ifdef CONFIG_PM
+static int serial_hs_lpc32xx_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);
+
+ uart_suspend_port(&lpc32xx_hs_reg, &p->port);
+
+ return 0;
+}
+
+static int serial_hs_lpc32xx_resume(struct platform_device *pdev)
+{
+ struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);
+
+ uart_resume_port(&lpc32xx_hs_reg, &p->port);
+
+ return 0;
+}
+#else
+#define serial_hs_lpc32xx_suspend NULL
+#define serial_hs_lpc32xx_resume NULL
+#endif
+
+static const struct of_device_id serial_hs_lpc32xx_dt_ids[] = {
+ { .compatible = "nxp,lpc3220-hsuart" },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, serial_hs_lpc32xx_dt_ids);
+
+static struct platform_driver serial_hs_lpc32xx_driver = {
+ .probe = serial_hs_lpc32xx_probe,
+ .remove = __devexit_p(serial_hs_lpc32xx_remove),
+ .suspend = serial_hs_lpc32xx_suspend,
+ .resume = serial_hs_lpc32xx_resume,
+ .driver = {
+ .name = MODNAME,
+ .owner = THIS_MODULE,
+ .of_match_table = serial_hs_lpc32xx_dt_ids,
+ },
+};
+
+static int __init lpc32xx_hsuart_init(void)
+{
+ int ret;
+
+ ret = uart_register_driver(&lpc32xx_hs_reg);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&serial_hs_lpc32xx_driver);
+ if (ret)
+ uart_unregister_driver(&lpc32xx_hs_reg);
+
+ return ret;
+}
+
+static void __exit lpc32xx_hsuart_exit(void)
+{
+ platform_driver_unregister(&serial_hs_lpc32xx_driver);
+ uart_unregister_driver(&lpc32xx_hs_reg);
+}
+
+module_init(lpc32xx_hsuart_init);
+module_exit(lpc32xx_hsuart_exit);
+
+MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");
+MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
+MODULE_DESCRIPTION("NXP LPC32XX High Speed UART driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index 5410c0637266..34e71874a892 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -208,6 +208,7 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = {
{ .compatible = "ns16750", .data = (void *)PORT_16750, },
{ .compatible = "ns16850", .data = (void *)PORT_16850, },
{ .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, },
+ { .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, },
#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
{ .compatible = "ibm,qpace-nwp-serial",
.data = (void *)PORT_NWPSERIAL, },
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 4fdec6a6b758..d291518a58a4 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -253,6 +253,9 @@ struct eg20t_port {
dma_addr_t rx_buf_dma;
struct dentry *debugfs;
+
+ /* protect the eg20t_port private structure and io access to membase */
+ spinlock_t lock;
};
/**
@@ -1058,7 +1061,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
int next = 1;
u8 msr;
- spin_lock_irqsave(&priv->port.lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
handled = 0;
while (next) {
iid = pch_uart_hal_get_iid(priv);
@@ -1116,7 +1119,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
handled |= (unsigned int)ret;
}
- spin_unlock_irqrestore(&priv->port.lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
return IRQ_RETVAL(handled);
}
@@ -1226,9 +1229,9 @@ static void pch_uart_break_ctl(struct uart_port *port, int ctl)
unsigned long flags;
priv = container_of(port, struct eg20t_port, port);
- spin_lock_irqsave(&port->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
pch_uart_hal_set_break(priv, ctl);
- spin_unlock_irqrestore(&port->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
/* Grab any interrupt resources and initialise any low level driver state. */
@@ -1376,7 +1379,8 @@ static void pch_uart_set_termios(struct uart_port *port,
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
- spin_lock_irqsave(&port->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
+ spin_lock(&port->lock);
uart_update_timeout(port, termios->c_cflag, baud);
rtn = pch_uart_hal_set_line(priv, baud, parity, bits, stb);
@@ -1389,7 +1393,8 @@ static void pch_uart_set_termios(struct uart_port *port,
tty_termios_encode_baud_rate(termios, baud, baud);
out:
- spin_unlock_irqrestore(&port->lock, flags);
+ spin_unlock(&port->lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
static const char *pch_uart_type(struct uart_port *port)
@@ -1538,8 +1543,9 @@ pch_console_write(struct console *co, const char *s, unsigned int count)
{
struct eg20t_port *priv;
unsigned long flags;
+ int priv_locked = 1;
+ int port_locked = 1;
u8 ier;
- int locked = 1;
priv = pch_uart_ports[co->index];
@@ -1547,12 +1553,16 @@ pch_console_write(struct console *co, const char *s, unsigned int count)
local_irq_save(flags);
if (priv->port.sysrq) {
- /* serial8250_handle_port() already took the lock */
- locked = 0;
+ spin_lock(&priv->lock);
+ /* serial8250_handle_port() already took the port lock */
+ port_locked = 0;
} else if (oops_in_progress) {
- locked = spin_trylock(&priv->port.lock);
- } else
+ priv_locked = spin_trylock(&priv->lock);
+ port_locked = spin_trylock(&priv->port.lock);
+ } else {
+ spin_lock(&priv->lock);
spin_lock(&priv->port.lock);
+ }
/*
* First save the IER then disable the interrupts
@@ -1570,8 +1580,10 @@ pch_console_write(struct console *co, const char *s, unsigned int count)
wait_for_xmitr(priv, BOTH_EMPTY);
iowrite8(ier, priv->membase + UART_IER);
- if (locked)
+ if (port_locked)
spin_unlock(&priv->port.lock);
+ if (priv_locked)
+ spin_unlock(&priv->lock);
local_irq_restore(flags);
}
@@ -1669,6 +1681,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
pci_enable_msi(pdev);
pci_set_master(pdev);
+ spin_lock_init(&priv->lock);
+
iobase = pci_resource_start(pdev, 0);
mapbase = pci_resource_start(pdev, 1);
priv->mapbase = mapbase;
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 5847a4b855f7..9033fc6e0e4e 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -670,9 +670,19 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
{
struct uart_pxa_port *up = serial_pxa_ports[co->index];
unsigned int ier;
+ unsigned long flags;
+ int locked = 1;
clk_prepare_enable(up->clk);
+ local_irq_save(flags);
+ if (up->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+ locked = spin_trylock(&up->port.lock);
+ else
+ spin_lock(&up->port.lock);
+
/*
* First save the IER then disable the interrupts
*/
@@ -688,6 +698,10 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
wait_for_xmitr(up);
serial_out(up, UART_IER, ier);
+ if (locked)
+ spin_unlock(&up->port.lock);
+ local_irq_restore(flags);
+
clk_disable_unprepare(up->clk);
}
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index d8b0aee35632..d57f165d6be8 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -529,7 +529,7 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
switch (level) {
case 3:
- if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
+ if (!IS_ERR(ourport->baudclk))
clk_disable(ourport->baudclk);
clk_disable(ourport->clk);
@@ -538,7 +538,7 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
case 0:
clk_enable(ourport->clk);
- if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
+ if (!IS_ERR(ourport->baudclk))
clk_enable(ourport->baudclk);
break;
@@ -604,7 +604,6 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
char clkname[MAX_CLK_NAME_LENGTH];
int calc_deviation, deviation = (1 << 30) - 1;
- *best_clk = NULL;
clk_sel = (ourport->cfg->clk_sel) ? ourport->cfg->clk_sel :
ourport->info->def_clk_sel;
for (cnt = 0; cnt < info->num_clks; cnt++) {
@@ -613,7 +612,7 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
sprintf(clkname, "clk_uart_baud%d", cnt);
clk = clk_get(ourport->port.dev, clkname);
- if (IS_ERR_OR_NULL(clk))
+ if (IS_ERR(clk))
continue;
rate = clk_get_rate(clk);
@@ -684,7 +683,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
{
struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
struct s3c24xx_uart_port *ourport = to_ourport(port);
- struct clk *clk = NULL;
+ struct clk *clk = ERR_PTR(-EINVAL);
unsigned long flags;
unsigned int baud, quot, clk_sel = 0;
unsigned int ulcon;
@@ -705,7 +704,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
quot = s3c24xx_serial_getclk(ourport, baud, &clk, &clk_sel);
if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
quot = port->custom_divisor;
- if (!clk)
+ if (IS_ERR(clk))
return;
/* check to see if we need to change clock source */
@@ -713,9 +712,9 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
if (ourport->baudclk != clk) {
s3c24xx_serial_setsource(port, clk_sel);
- if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
+ if (!IS_ERR(ourport->baudclk)) {
clk_disable(ourport->baudclk);
- ourport->baudclk = NULL;
+ ourport->baudclk = ERR_PTR(-EINVAL);
}
clk_enable(clk);
@@ -1014,10 +1013,10 @@ static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,
* a disturbance in the clock-rate over the change.
*/
- if (IS_ERR(port->clk))
+ if (IS_ERR(port->baudclk))
goto exit;
- if (port->baudclk_rate == clk_get_rate(port->clk))
+ if (port->baudclk_rate == clk_get_rate(port->baudclk))
goto exit;
if (val == CPUFREQ_PRECHANGE) {
@@ -1160,7 +1159,11 @@ static ssize_t s3c24xx_serial_show_clksrc(struct device *dev,
struct uart_port *port = s3c24xx_dev_to_port(dev);
struct s3c24xx_uart_port *ourport = to_ourport(port);
- return snprintf(buf, PAGE_SIZE, "* %s\n", ourport->baudclk->name);
+ if (IS_ERR(ourport->baudclk))
+ return -EINVAL;
+
+ return snprintf(buf, PAGE_SIZE, "* %s\n",
+ ourport->baudclk->name ?: "(null)");
}
static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL);
@@ -1200,6 +1203,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
return -ENODEV;
}
+ ourport->baudclk = ERR_PTR(-EINVAL);
ourport->info = ourport->drv_data->info;
ourport->cfg = (pdev->dev.platform_data) ?
(struct s3c2410_uartcfg *)pdev->dev.platform_data :
@@ -1387,7 +1391,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
sprintf(clk_name, "clk_uart_baud%d", clk_sel);
clk = clk_get(port->dev, clk_name);
- if (!IS_ERR(clk) && clk != NULL)
+ if (!IS_ERR(clk))
rate = clk_get_rate(clk);
else
rate = 1;
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 246b823c1b27..a21dc8e3b7c0 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2527,14 +2527,16 @@ void uart_insert_char(struct uart_port *port, unsigned int status,
struct tty_struct *tty = port->state->port.tty;
if ((status & port->ignore_status_mask & ~overrun) == 0)
- tty_insert_flip_char(tty, ch, flag);
+ if (tty_insert_flip_char(tty, ch, flag) == 0)
+ ++port->icount.buf_overrun;
/*
* Overrun is special. Since it's reported immediately,
* it doesn't affect the current character.
*/
if (status & ~port->ignore_status_mask & overrun)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ if (tty_insert_flip_char(tty, 0, TTY_OVERRUN) == 0)
+ ++port->icount.buf_overrun;
}
EXPORT_SYMBOL_GPL(uart_insert_char);
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
index 593d40ad0a6b..5ed0daae6564 100644
--- a/drivers/tty/synclink.c
+++ b/drivers/tty/synclink.c
@@ -3338,9 +3338,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
printk("%s(%d):block_til_ready blocking on %s count=%d\n",
__FILE__,__LINE__, tty->driver->name, port->count );
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
index aa1debf97cc7..45b43f11ca39 100644
--- a/drivers/tty/synclink_gt.c
+++ b/drivers/tty/synclink_gt.c
@@ -3336,9 +3336,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
}
DBGINFO(("%s block_til_ready wait\n", tty->driver->name));
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c
index a3dddc12d2fe..4a1e4f07765b 100644
--- a/drivers/tty/synclinkmp.c
+++ b/drivers/tty/synclinkmp.c
@@ -3357,9 +3357,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
printk("%s(%d):%s block_til_ready() count=%d\n",
__FILE__,__LINE__, tty->driver->name, port->count );
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index b425c79675ad..ca7c25d9f6d5 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -185,6 +185,7 @@ void free_tty_struct(struct tty_struct *tty)
put_device(tty->dev);
kfree(tty->write_buf);
tty_buffer_free_all(tty);
+ tty->magic = 0xDEADDEAD;
kfree(tty);
}
@@ -573,7 +574,7 @@ void __tty_hangup(struct tty_struct *tty)
}
spin_unlock(&redirect_lock);
- tty_lock();
+ tty_lock(tty);
/* some functions below drop BTM, so we need this bit */
set_bit(TTY_HUPPING, &tty->flags);
@@ -666,7 +667,7 @@ void __tty_hangup(struct tty_struct *tty)
clear_bit(TTY_HUPPING, &tty->flags);
tty_ldisc_enable(tty);
- tty_unlock();
+ tty_unlock(tty);
if (f)
fput(f);
@@ -1103,12 +1104,12 @@ void tty_write_message(struct tty_struct *tty, char *msg)
{
if (tty) {
mutex_lock(&tty->atomic_write_lock);
- tty_lock();
+ tty_lock(tty);
if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) {
- tty_unlock();
+ tty_unlock(tty);
tty->ops->write(tty, msg, strlen(msg));
} else
- tty_unlock();
+ tty_unlock(tty);
tty_write_unlock(tty);
}
return;
@@ -1403,10 +1404,14 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
}
initialize_tty_struct(tty, driver, idx);
+ tty_lock(tty);
retval = tty_driver_install_tty(driver, tty);
if (retval < 0)
goto err_deinit_tty;
+ if (!tty->port)
+ tty->port = driver->ports[idx];
+
/*
* Structures all installed ... call the ldisc open routines.
* If we fail here just call release_tty to clean up. No need
@@ -1415,9 +1420,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
retval = tty_ldisc_setup(tty, tty->link);
if (retval)
goto err_release_tty;
+ /* Return the tty locked so that it cannot vanish under the caller */
return tty;
err_deinit_tty:
+ tty_unlock(tty);
deinitialize_tty_struct(tty);
free_tty_struct(tty);
err_module_put:
@@ -1426,6 +1433,7 @@ err_module_put:
/* call the tty release_tty routine to clean out this slot */
err_release_tty:
+ tty_unlock(tty);
printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, "
"clearing slot %d\n", idx);
release_tty(tty, idx);
@@ -1628,7 +1636,7 @@ int tty_release(struct inode *inode, struct file *filp)
if (tty_paranoia_check(tty, inode, __func__))
return 0;
- tty_lock();
+ tty_lock(tty);
check_tty_count(tty, __func__);
__tty_fasync(-1, filp, 0);
@@ -1637,10 +1645,11 @@ int tty_release(struct inode *inode, struct file *filp)
pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER);
devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
+ /* Review: parallel close */
o_tty = tty->link;
if (tty_release_checks(tty, o_tty, idx)) {
- tty_unlock();
+ tty_unlock(tty);
return 0;
}
@@ -1652,7 +1661,7 @@ int tty_release(struct inode *inode, struct file *filp)
if (tty->ops->close)
tty->ops->close(tty, filp);
- tty_unlock();
+ tty_unlock(tty);
/*
* Sanity check: if tty->count is going to zero, there shouldn't be
* any waiters on tty->read_wait or tty->write_wait. We test the
@@ -1675,7 +1684,7 @@ int tty_release(struct inode *inode, struct file *filp)
opens on /dev/tty */
mutex_lock(&tty_mutex);
- tty_lock();
+ tty_lock_pair(tty, o_tty);
tty_closing = tty->count <= 1;
o_tty_closing = o_tty &&
(o_tty->count <= (pty_master ? 1 : 0));
@@ -1706,7 +1715,7 @@ int tty_release(struct inode *inode, struct file *filp)
printk(KERN_WARNING "%s: %s: read/write wait queue active!\n",
__func__, tty_name(tty, buf));
- tty_unlock();
+ tty_unlock_pair(tty, o_tty);
mutex_unlock(&tty_mutex);
schedule();
}
@@ -1769,7 +1778,7 @@ int tty_release(struct inode *inode, struct file *filp)
/* check whether both sides are closing ... */
if (!tty_closing || (o_tty && !o_tty_closing)) {
- tty_unlock();
+ tty_unlock_pair(tty, o_tty);
return 0;
}
@@ -1782,14 +1791,16 @@ int tty_release(struct inode *inode, struct file *filp)
tty_ldisc_release(tty, o_tty);
/*
* The release_tty function takes care of the details of clearing
- * the slots and preserving the termios structure.
+ * the slots and preserving the termios structure. The tty_unlock_pair
+ * should be safe as we keep a kref while the tty is locked (so the
+ * unlock never unlocks a freed tty).
*/
release_tty(tty, idx);
+ tty_unlock_pair(tty, o_tty);
/* Make this pty number available for reallocation */
if (devpts)
devpts_kill_index(inode, idx);
- tty_unlock();
return 0;
}
@@ -1893,6 +1904,9 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp,
* Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev.
* tty->count should protect the rest.
* ->siglock protects ->signal/->sighand
+ *
+ * Note: the tty_unlock/lock cases without a ref are only safe due to
+ * tty_mutex
*/
static int tty_open(struct inode *inode, struct file *filp)
@@ -1916,8 +1930,7 @@ retry_open:
retval = 0;
mutex_lock(&tty_mutex);
- tty_lock();
-
+ /* This is protected by the tty_mutex */
tty = tty_open_current_tty(device, filp);
if (IS_ERR(tty)) {
retval = PTR_ERR(tty);
@@ -1938,17 +1951,19 @@ retry_open:
}
if (tty) {
+ tty_lock(tty);
retval = tty_reopen(tty);
- if (retval)
+ if (retval < 0) {
+ tty_unlock(tty);
tty = ERR_PTR(retval);
- } else
+ }
+ } else /* Returns with the tty_lock held for now */
tty = tty_init_dev(driver, index);
mutex_unlock(&tty_mutex);
if (driver)
tty_driver_kref_put(driver);
if (IS_ERR(tty)) {
- tty_unlock();
retval = PTR_ERR(tty);
goto err_file;
}
@@ -1977,7 +1992,7 @@ retry_open:
printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__,
retval, tty->name);
#endif
- tty_unlock(); /* need to call tty_release without BTM */
+ tty_unlock(tty); /* need to call tty_release without BTM */
tty_release(inode, filp);
if (retval != -ERESTARTSYS)
return retval;
@@ -1989,17 +2004,15 @@ retry_open:
/*
* Need to reset f_op in case a hangup happened.
*/
- tty_lock();
if (filp->f_op == &hung_up_tty_fops)
filp->f_op = &tty_fops;
- tty_unlock();
goto retry_open;
}
- tty_unlock();
+ tty_unlock(tty);
mutex_lock(&tty_mutex);
- tty_lock();
+ tty_lock(tty);
spin_lock_irq(&current->sighand->siglock);
if (!noctty &&
current->signal->leader &&
@@ -2007,11 +2020,10 @@ retry_open:
tty->session == NULL)
__proc_set_tty(current, tty);
spin_unlock_irq(&current->sighand->siglock);
- tty_unlock();
+ tty_unlock(tty);
mutex_unlock(&tty_mutex);
return 0;
err_unlock:
- tty_unlock();
mutex_unlock(&tty_mutex);
/* after locks to avoid deadlock */
if (!IS_ERR_OR_NULL(driver))
@@ -2094,10 +2106,13 @@ out:
static int tty_fasync(int fd, struct file *filp, int on)
{
+ struct tty_struct *tty = file_tty(filp);
int retval;
- tty_lock();
+
+ tty_lock(tty);
retval = __tty_fasync(fd, filp, on);
- tty_unlock();
+ tty_unlock(tty);
+
return retval;
}
@@ -2934,6 +2949,7 @@ void initialize_tty_struct(struct tty_struct *tty,
tty->pgrp = NULL;
tty->overrun_time = jiffies;
tty_buffer_init(tty);
+ mutex_init(&tty->legacy_mutex);
mutex_init(&tty->termios_mutex);
mutex_init(&tty->ldisc_mutex);
init_waitqueue_head(&tty->write_wait);
@@ -3094,6 +3110,7 @@ static void destruct_tty_driver(struct kref *kref)
kfree(p);
cdev_del(&driver->cdev);
}
+ kfree(driver->ports);
kfree(driver);
}
@@ -3132,6 +3149,18 @@ int tty_register_driver(struct tty_driver *driver)
if (!p)
return -ENOMEM;
}
+ /*
+ * There is too many lines in PTY and we won't need the array there
+ * since it has an ->install hook where it assigns ports properly.
+ */
+ if (driver->type != TTY_DRIVER_TYPE_PTY) {
+ driver->ports = kcalloc(driver->num, sizeof(struct tty_port *),
+ GFP_KERNEL);
+ if (!driver->ports) {
+ error = -ENOMEM;
+ goto err_free_p;
+ }
+ }
if (!driver->major) {
error = alloc_chrdev_region(&dev, driver->minor_start,
@@ -3144,10 +3173,8 @@ int tty_register_driver(struct tty_driver *driver)
dev = MKDEV(driver->major, driver->minor_start);
error = register_chrdev_region(dev, driver->num, driver->name);
}
- if (error < 0) {
- kfree(p);
- return error;
- }
+ if (error < 0)
+ goto err_free_p;
if (p) {
driver->ttys = (struct tty_struct **)p;
@@ -3160,13 +3187,8 @@ int tty_register_driver(struct tty_driver *driver)
cdev_init(&driver->cdev, &tty_fops);
driver->cdev.owner = driver->owner;
error = cdev_add(&driver->cdev, dev, driver->num);
- if (error) {
- unregister_chrdev_region(dev, driver->num);
- driver->ttys = NULL;
- driver->termios = NULL;
- kfree(p);
- return error;
- }
+ if (error)
+ goto err_unreg_char;
mutex_lock(&tty_mutex);
list_add(&driver->tty_drivers, &tty_drivers);
@@ -3193,13 +3215,14 @@ err:
list_del(&driver->tty_drivers);
mutex_unlock(&tty_mutex);
+err_unreg_char:
unregister_chrdev_region(dev, driver->num);
driver->ttys = NULL;
driver->termios = NULL;
+err_free_p: /* destruct_tty_driver will free driver->ports */
kfree(p);
return error;
}
-
EXPORT_SYMBOL(tty_register_driver);
/*
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 9911eb6b34cd..847f7ed7a3ed 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -568,7 +568,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
if (IS_ERR(new_ldisc))
return PTR_ERR(new_ldisc);
- tty_lock();
+ tty_lock(tty);
/*
* We need to look at the tty locking here for pty/tty pairs
* when both sides try to change in parallel.
@@ -582,12 +582,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
*/
if (tty->ldisc->ops->num == ldisc) {
- tty_unlock();
+ tty_unlock(tty);
tty_ldisc_put(new_ldisc);
return 0;
}
- tty_unlock();
+ tty_unlock(tty);
/*
* Problem: What do we do if this blocks ?
* We could deadlock here
@@ -595,7 +595,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
tty_wait_until_sent(tty, 0);
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
/*
@@ -605,10 +605,10 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) {
mutex_unlock(&tty->ldisc_mutex);
- tty_unlock();
+ tty_unlock(tty);
wait_event(tty_ldisc_wait,
test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0);
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
}
@@ -623,7 +623,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
o_ldisc = tty->ldisc;
- tty_unlock();
+ tty_unlock(tty);
/*
* Make sure we don't change while someone holds a
* reference to the line discipline. The TTY_LDISC bit
@@ -650,7 +650,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
retval = tty_ldisc_wait_idle(tty, 5 * HZ);
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
/* handle wait idle failure locked */
@@ -659,13 +659,13 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
goto enable;
}
- if (test_bit(TTY_HUPPED, &tty->flags)) {
+ if (test_bit(TTY_HUPPING, &tty->flags)) {
/* We were raced by the hangup method. It will have stomped
the ldisc data and closed the ldisc down */
clear_bit(TTY_LDISC_CHANGING, &tty->flags);
mutex_unlock(&tty->ldisc_mutex);
tty_ldisc_put(new_ldisc);
- tty_unlock();
+ tty_unlock(tty);
return -EIO;
}
@@ -708,7 +708,7 @@ enable:
if (o_work)
schedule_work(&o_tty->buf.work);
mutex_unlock(&tty->ldisc_mutex);
- tty_unlock();
+ tty_unlock(tty);
return retval;
}
@@ -816,11 +816,11 @@ void tty_ldisc_hangup(struct tty_struct *tty)
* need to wait for another function taking the BTM
*/
clear_bit(TTY_LDISC, &tty->flags);
- tty_unlock();
+ tty_unlock(tty);
cancel_work_sync(&tty->buf.work);
mutex_unlock(&tty->ldisc_mutex);
retry:
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
/* At this point we have a closed ldisc and we want to
@@ -831,7 +831,7 @@ retry:
if (atomic_read(&tty->ldisc->users) != 1) {
char cur_n[TASK_COMM_LEN], tty_n[64];
long timeout = 3 * HZ;
- tty_unlock();
+ tty_unlock(tty);
while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
timeout = MAX_SCHEDULE_TIMEOUT;
@@ -894,6 +894,23 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
tty_ldisc_enable(tty);
return 0;
}
+
+static void tty_ldisc_kill(struct tty_struct *tty)
+{
+ mutex_lock(&tty->ldisc_mutex);
+ /*
+ * Now kill off the ldisc
+ */
+ tty_ldisc_close(tty, tty->ldisc);
+ tty_ldisc_put(tty->ldisc);
+ /* Force an oops if we mess this up */
+ tty->ldisc = NULL;
+
+ /* Ensure the next open requests the N_TTY ldisc */
+ tty_set_termios_ldisc(tty, N_TTY);
+ mutex_unlock(&tty->ldisc_mutex);
+}
+
/**
* tty_ldisc_release - release line discipline
* @tty: tty being shut down
@@ -912,27 +929,19 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
* race with the set_ldisc code path.
*/
- tty_unlock();
+ tty_unlock_pair(tty, o_tty);
tty_ldisc_halt(tty);
tty_ldisc_flush_works(tty);
- tty_lock();
-
- mutex_lock(&tty->ldisc_mutex);
- /*
- * Now kill off the ldisc
- */
- tty_ldisc_close(tty, tty->ldisc);
- tty_ldisc_put(tty->ldisc);
- /* Force an oops if we mess this up */
- tty->ldisc = NULL;
+ if (o_tty) {
+ tty_ldisc_halt(o_tty);
+ tty_ldisc_flush_works(o_tty);
+ }
+ tty_lock_pair(tty, o_tty);
- /* Ensure the next open requests the N_TTY ldisc */
- tty_set_termios_ldisc(tty, N_TTY);
- mutex_unlock(&tty->ldisc_mutex);
- /* This will need doing differently if we need to lock */
+ tty_ldisc_kill(tty);
if (o_tty)
- tty_ldisc_release(o_tty, NULL);
+ tty_ldisc_kill(o_tty);
/* And the memory resources remaining (buffers, termios) will be
disposed of when the kref hits zero */
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c
index 9ff986c32a21..67feac9e6ebb 100644
--- a/drivers/tty/tty_mutex.c
+++ b/drivers/tty/tty_mutex.c
@@ -4,29 +4,70 @@
#include <linux/semaphore.h>
#include <linux/sched.h>
-/*
- * The 'big tty mutex'
- *
- * This mutex is taken and released by tty_lock() and tty_unlock(),
- * replacing the older big kernel lock.
- * It can no longer be taken recursively, and does not get
- * released implicitly while sleeping.
- *
- * Don't use in new code.
- */
-static DEFINE_MUTEX(big_tty_mutex);
+/* Legacy tty mutex glue */
+
+enum {
+ TTY_MUTEX_NORMAL,
+ TTY_MUTEX_NESTED,
+};
/*
* Getting the big tty mutex.
*/
-void __lockfunc tty_lock(void)
+
+static void __lockfunc tty_lock_nested(struct tty_struct *tty,
+ unsigned int subclass)
{
- mutex_lock(&big_tty_mutex);
+ if (tty->magic != TTY_MAGIC) {
+ printk(KERN_ERR "L Bad %p\n", tty);
+ WARN_ON(1);
+ return;
+ }
+ tty_kref_get(tty);
+ mutex_lock_nested(&tty->legacy_mutex, subclass);
+}
+
+void __lockfunc tty_lock(struct tty_struct *tty)
+{
+ return tty_lock_nested(tty, TTY_MUTEX_NORMAL);
}
EXPORT_SYMBOL(tty_lock);
-void __lockfunc tty_unlock(void)
+void __lockfunc tty_unlock(struct tty_struct *tty)
{
- mutex_unlock(&big_tty_mutex);
+ if (tty->magic != TTY_MAGIC) {
+ printk(KERN_ERR "U Bad %p\n", tty);
+ WARN_ON(1);
+ return;
+ }
+ mutex_unlock(&tty->legacy_mutex);
+ tty_kref_put(tty);
}
EXPORT_SYMBOL(tty_unlock);
+
+/*
+ * Getting the big tty mutex for a pair of ttys with lock ordering
+ * On a non pty/tty pair tty2 can be NULL which is just fine.
+ */
+void __lockfunc tty_lock_pair(struct tty_struct *tty,
+ struct tty_struct *tty2)
+{
+ if (tty < tty2) {
+ tty_lock(tty);
+ tty_lock_nested(tty2, TTY_MUTEX_NESTED);
+ } else {
+ if (tty2 && tty2 != tty)
+ tty_lock(tty2);
+ tty_lock_nested(tty, TTY_MUTEX_NESTED);
+ }
+}
+EXPORT_SYMBOL(tty_lock_pair);
+
+void __lockfunc tty_unlock_pair(struct tty_struct *tty,
+ struct tty_struct *tty2)
+{
+ tty_unlock(tty);
+ if (tty2 && tty2 != tty)
+ tty_unlock(tty2);
+}
+EXPORT_SYMBOL(tty_unlock_pair);
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index bf6e238146ae..a3ba776c574c 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -33,6 +33,15 @@ void tty_port_init(struct tty_port *port)
}
EXPORT_SYMBOL(tty_port_init);
+struct device *tty_port_register_device(struct tty_port *port,
+ struct tty_driver *driver, unsigned index,
+ struct device *device)
+{
+ driver->ports[index] = port;
+ return tty_register_device(driver, index, device);
+}
+EXPORT_SYMBOL_GPL(tty_port_register_device);
+
int tty_port_alloc_xmit_buf(struct tty_port *port)
{
/* We may sleep in get_zeroed_page() */
@@ -230,7 +239,7 @@ int tty_port_block_til_ready(struct tty_port *port,
/* block if port is in the process of being closed */
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
- wait_event_interruptible_tty(port->close_wait,
+ wait_event_interruptible_tty(tty, port->close_wait,
!(port->flags & ASYNC_CLOSING));
if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
@@ -296,9 +305,9 @@ int tty_port_block_til_ready(struct tty_port *port,
retval = -ERESTARTSYS;
break;
}
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
finish_wait(&port->open_wait, &wait);
@@ -413,6 +422,14 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty,
}
EXPORT_SYMBOL(tty_port_close);
+int tty_port_install(struct tty_port *port, struct tty_driver *driver,
+ struct tty_struct *tty)
+{
+ tty->port = port;
+ return tty_standard_install(driver, tty);
+}
+EXPORT_SYMBOL_GPL(tty_port_install);
+
int tty_port_open(struct tty_port *port, struct tty_struct *tty,
struct file *filp)
{
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 48cc6f25cfd3..9b4f60a6ab0e 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -310,7 +310,7 @@ static void put_queue(struct vc_data *vc, int ch)
if (tty) {
tty_insert_flip_char(tty, ch, 0);
- con_schedule_flip(tty);
+ tty_schedule_flip(tty);
}
}
@@ -325,7 +325,7 @@ static void puts_queue(struct vc_data *vc, char *cp)
tty_insert_flip_char(tty, *cp, 0);
cp++;
}
- con_schedule_flip(tty);
+ tty_schedule_flip(tty);
}
static void applkey(struct vc_data *vc, int key, char mode)
@@ -586,7 +586,7 @@ static void fn_send_intr(struct vc_data *vc)
if (!tty)
return;
tty_insert_flip_char(tty, 0, TTY_BREAK);
- con_schedule_flip(tty);
+ tty_schedule_flip(tty);
}
static void fn_scroll_forw(struct vc_data *vc)
@@ -1049,13 +1049,10 @@ static int kbd_update_leds_helper(struct input_handle *handle, void *data)
*/
int vt_get_leds(int console, int flag)
{
- unsigned long flags;
struct kbd_struct * kbd = kbd_table + console;
int ret;
- spin_lock_irqsave(&kbd_event_lock, flags);
ret = vc_kbd_led(kbd, flag);
- spin_unlock_irqrestore(&kbd_event_lock, flags);
return ret;
}
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 84cbf298c094..7cb53c236339 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -1380,7 +1380,7 @@ static void respond_string(const char *p, struct tty_struct *tty)
tty_insert_flip_char(tty, *p, 0);
p++;
}
- con_schedule_flip(tty);
+ tty_schedule_flip(tty);
}
static void cursor_report(struct vc_data *vc, struct tty_struct *tty)
@@ -2792,41 +2792,52 @@ static void con_flush_chars(struct tty_struct *tty)
/*
* Allocate the console screen memory.
*/
-static int con_open(struct tty_struct *tty, struct file *filp)
+static int con_install(struct tty_driver *driver, struct tty_struct *tty)
{
unsigned int currcons = tty->index;
- int ret = 0;
+ struct vc_data *vc;
+ int ret;
console_lock();
- if (tty->driver_data == NULL) {
- ret = vc_allocate(currcons);
- if (ret == 0) {
- struct vc_data *vc = vc_cons[currcons].d;
+ ret = vc_allocate(currcons);
+ if (ret)
+ goto unlock;
- /* Still being freed */
- if (vc->port.tty) {
- console_unlock();
- return -ERESTARTSYS;
- }
- tty->driver_data = vc;
- vc->port.tty = tty;
+ vc = vc_cons[currcons].d;
- if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
- tty->winsize.ws_row = vc_cons[currcons].d->vc_rows;
- tty->winsize.ws_col = vc_cons[currcons].d->vc_cols;
- }
- if (vc->vc_utf)
- tty->termios->c_iflag |= IUTF8;
- else
- tty->termios->c_iflag &= ~IUTF8;
- console_unlock();
- return ret;
- }
+ /* Still being freed */
+ if (vc->port.tty) {
+ ret = -ERESTARTSYS;
+ goto unlock;
}
+
+ ret = tty_port_install(&vc->port, driver, tty);
+ if (ret)
+ goto unlock;
+
+ tty->driver_data = vc;
+ vc->port.tty = tty;
+
+ if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
+ tty->winsize.ws_row = vc_cons[currcons].d->vc_rows;
+ tty->winsize.ws_col = vc_cons[currcons].d->vc_cols;
+ }
+ if (vc->vc_utf)
+ tty->termios->c_iflag |= IUTF8;
+ else
+ tty->termios->c_iflag &= ~IUTF8;
+unlock:
console_unlock();
return ret;
}
+static int con_open(struct tty_struct *tty, struct file *filp)
+{
+ /* everything done in install */
+ return 0;
+}
+
+
static void con_close(struct tty_struct *tty, struct file *filp)
{
/* Nothing to do - we defer to shutdown */
@@ -2947,6 +2958,7 @@ static int __init con_init(void)
console_initcall(con_init);
static const struct tty_operations con_ops = {
+ .install = con_install,
.open = con_open,
.close = con_close,
.write = con_write,
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index 64618547be11..b841f56d2e66 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -110,16 +110,7 @@ void vt_event_post(unsigned int event, unsigned int old, unsigned int new)
wake_up_interruptible(&vt_event_waitqueue);
}
-/**
- * vt_event_wait - wait for an event
- * @vw: our event
- *
- * Waits for an event to occur which completes our vt_event_wait
- * structure. On return the structure has wv->done set to 1 for success
- * or 0 if some event such as a signal ended the wait.
- */
-
-static void vt_event_wait(struct vt_event_wait *vw)
+static void __vt_event_queue(struct vt_event_wait *vw)
{
unsigned long flags;
/* Prepare the event */
@@ -129,8 +120,18 @@ static void vt_event_wait(struct vt_event_wait *vw)
spin_lock_irqsave(&vt_event_lock, flags);
list_add(&vw->list, &vt_events);
spin_unlock_irqrestore(&vt_event_lock, flags);
+}
+
+static void __vt_event_wait(struct vt_event_wait *vw)
+{
/* Wait for it to pass */
wait_event_interruptible(vt_event_waitqueue, vw->done);
+}
+
+static void __vt_event_dequeue(struct vt_event_wait *vw)
+{
+ unsigned long flags;
+
/* Dequeue it */
spin_lock_irqsave(&vt_event_lock, flags);
list_del(&vw->list);
@@ -138,6 +139,22 @@ static void vt_event_wait(struct vt_event_wait *vw)
}
/**
+ * vt_event_wait - wait for an event
+ * @vw: our event
+ *
+ * Waits for an event to occur which completes our vt_event_wait
+ * structure. On return the structure has wv->done set to 1 for success
+ * or 0 if some event such as a signal ended the wait.
+ */
+
+static void vt_event_wait(struct vt_event_wait *vw)
+{
+ __vt_event_queue(vw);
+ __vt_event_wait(vw);
+ __vt_event_dequeue(vw);
+}
+
+/**
* vt_event_wait_ioctl - event ioctl handler
* @arg: argument to ioctl
*
@@ -177,10 +194,14 @@ int vt_waitactive(int n)
{
struct vt_event_wait vw;
do {
- if (n == fg_console + 1)
- break;
vw.event.event = VT_EVENT_SWITCH;
- vt_event_wait(&vw);
+ __vt_event_queue(&vw);
+ if (n == fg_console + 1) {
+ __vt_event_dequeue(&vw);
+ break;
+ }
+ __vt_event_wait(&vw);
+ __vt_event_dequeue(&vw);
if (vw.done == 0)
return -EINTR;
} while (vw.event.newev != n);
diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c
index d47eb06fe463..7ae9af6b2a54 100644
--- a/drivers/usb/serial/metro-usb.c
+++ b/drivers/usb/serial/metro-usb.c
@@ -130,20 +130,14 @@ static void metrousb_read_int_callback(struct urb *urb)
/* Set the data read from the usb port into the serial port buffer. */
tty = tty_port_tty_get(&port->port);
- if (!tty) {
- dev_err(&port->dev, "%s - bad tty pointer - exiting\n",
- __func__);
- return;
- }
-
if (tty && urb->actual_length) {
/* Loop through the data copying each byte to the tty layer. */
tty_insert_flip_string(tty, data, urb->actual_length);
/* Force the data to the tty layer. */
tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
}
- tty_kref_put(tty);
/* Set any port variables. */
spin_lock_irqsave(&metro_priv->lock, flags);
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 27483f91a4a3..da67abb1945e 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -207,7 +207,7 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
if (retval)
goto error_get_interface;
- retval = tty_standard_install(driver, tty);
+ retval = tty_port_install(&port->port, driver, tty);
if (retval)
goto error_init_termios;
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 8760be30b375..cf41085e3331 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -84,7 +84,6 @@ header-y += capability.h
header-y += capi.h
header-y += cciss_defs.h
header-y += cciss_ioctl.h
-header-y += cdk.h
header-y += cdrom.h
header-y += cgroupstats.h
header-y += chio.h
@@ -93,7 +92,6 @@ header-y += cn_proc.h
header-y += coda.h
header-y += coda_psdev.h
header-y += coff.h
-header-y += comstats.h
header-y += connector.h
header-y += const.h
header-y += cramfs_fs.h
@@ -140,7 +138,6 @@ header-y += fuse.h
header-y += futex.h
header-y += gameport.h
header-y += gen_stats.h
-header-y += generic_serial.h
header-y += genetlink.h
header-y += gfs2_ondisk.h
header-y += gigaset_dev.h
diff --git a/include/linux/cd1400.h b/include/linux/cd1400.h
deleted file mode 100644
index 1dc3ab0523fd..000000000000
--- a/include/linux/cd1400.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/*****************************************************************************/
-
-/*
- * cd1400.h -- cd1400 UART hardware info.
- *
- * Copyright (C) 1996-1998 Stallion Technologies
- * Copyright (C) 1994-1996 Greg Ungerer.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*****************************************************************************/
-#ifndef _CD1400_H
-#define _CD1400_H
-/*****************************************************************************/
-
-/*
- * Define the number of async ports per cd1400 uart chip.
- */
-#define CD1400_PORTS 4
-
-/*
- * Define the cd1400 uarts internal FIFO sizes.
- */
-#define CD1400_TXFIFOSIZE 12
-#define CD1400_RXFIFOSIZE 12
-
-/*
- * Local RX FIFO thresh hold level. Also define the RTS thresh hold
- * based on the RX thresh hold.
- */
-#define FIFO_RXTHRESHOLD 6
-#define FIFO_RTSTHRESHOLD 7
-
-/*****************************************************************************/
-
-/*
- * Define the cd1400 register addresses. These are all the valid
- * registers with the cd1400. Some are global, some virtual, some
- * per port.
- */
-#define GFRCR 0x40
-#define CAR 0x68
-#define GCR 0x4b
-#define SVRR 0x67
-#define RICR 0x44
-#define TICR 0x45
-#define MICR 0x46
-#define RIR 0x6b
-#define TIR 0x6a
-#define MIR 0x69
-#define PPR 0x7e
-
-#define RIVR 0x43
-#define TIVR 0x42
-#define MIVR 0x41
-#define TDR 0x63
-#define RDSR 0x62
-#define MISR 0x4c
-#define EOSRR 0x60
-
-#define LIVR 0x18
-#define CCR 0x05
-#define SRER 0x06
-#define COR1 0x08
-#define COR2 0x09
-#define COR3 0x0a
-#define COR4 0x1e
-#define COR5 0x1f
-#define CCSR 0x0b
-#define RDCR 0x0e
-#define SCHR1 0x1a
-#define SCHR2 0x1b
-#define SCHR3 0x1c
-#define SCHR4 0x1d
-#define SCRL 0x22
-#define SCRH 0x23
-#define LNC 0x24
-#define MCOR1 0x15
-#define MCOR2 0x16
-#define RTPR 0x21
-#define MSVR1 0x6c
-#define MSVR2 0x6d
-#define PSVR 0x6f
-#define RBPR 0x78
-#define RCOR 0x7c
-#define TBPR 0x72
-#define TCOR 0x76
-
-/*****************************************************************************/
-
-/*
- * Define the set of baud rate clock divisors.
- */
-#define CD1400_CLK0 8
-#define CD1400_CLK1 32
-#define CD1400_CLK2 128
-#define CD1400_CLK3 512
-#define CD1400_CLK4 2048
-
-#define CD1400_NUMCLKS 5
-
-/*****************************************************************************/
-
-/*
- * Define the clock pre-scalar value to be a 5 ms clock. This should be
- * OK for now. It would probably be better to make it 10 ms, but we
- * can't fit that divisor into 8 bits!
- */
-#define PPR_SCALAR 244
-
-/*****************************************************************************/
-
-/*
- * Define values used to set character size options.
- */
-#define COR1_CHL5 0x00
-#define COR1_CHL6 0x01
-#define COR1_CHL7 0x02
-#define COR1_CHL8 0x03
-
-/*
- * Define values used to set the number of stop bits.
- */
-#define COR1_STOP1 0x00
-#define COR1_STOP15 0x04
-#define COR1_STOP2 0x08
-
-/*
- * Define values used to set the parity scheme in use.
- */
-#define COR1_PARNONE 0x00
-#define COR1_PARFORCE 0x20
-#define COR1_PARENB 0x40
-#define COR1_PARIGNORE 0x10
-
-#define COR1_PARODD 0x80
-#define COR1_PAREVEN 0x00
-
-#define COR2_IXM 0x80
-#define COR2_TXIBE 0x40
-#define COR2_ETC 0x20
-#define COR2_LLM 0x10
-#define COR2_RLM 0x08
-#define COR2_RTSAO 0x04
-#define COR2_CTSAE 0x02
-
-#define COR3_SCDRNG 0x80
-#define COR3_SCD34 0x40
-#define COR3_FCT 0x20
-#define COR3_SCD12 0x10
-
-/*
- * Define values used by COR4.
- */
-#define COR4_BRKINT 0x08
-#define COR4_IGNBRK 0x18
-
-/*****************************************************************************/
-
-/*
- * Define the modem control register values.
- * Note that the actual hardware is a little different to the conventional
- * pin names on the cd1400.
- */
-#define MSVR1_DTR 0x01
-#define MSVR1_DSR 0x10
-#define MSVR1_RI 0x20
-#define MSVR1_CTS 0x40
-#define MSVR1_DCD 0x80
-
-#define MSVR2_RTS 0x02
-#define MSVR2_DSR 0x10
-#define MSVR2_RI 0x20
-#define MSVR2_CTS 0x40
-#define MSVR2_DCD 0x80
-
-#define MCOR1_DCD 0x80
-#define MCOR1_CTS 0x40
-#define MCOR1_RI 0x20
-#define MCOR1_DSR 0x10
-
-#define MCOR2_DCD 0x80
-#define MCOR2_CTS 0x40
-#define MCOR2_RI 0x20
-#define MCOR2_DSR 0x10
-
-/*****************************************************************************/
-
-/*
- * Define the bits used with the service (interrupt) enable register.
- */
-#define SRER_NNDT 0x01
-#define SRER_TXEMPTY 0x02
-#define SRER_TXDATA 0x04
-#define SRER_RXDATA 0x10
-#define SRER_MODEM 0x80
-
-/*****************************************************************************/
-
-/*
- * Define operational commands for the command register.
- */
-#define CCR_RESET 0x80
-#define CCR_CORCHANGE 0x4e
-#define CCR_SENDCH 0x20
-#define CCR_CHANCTRL 0x10
-
-#define CCR_TXENABLE (CCR_CHANCTRL | 0x08)
-#define CCR_TXDISABLE (CCR_CHANCTRL | 0x04)
-#define CCR_RXENABLE (CCR_CHANCTRL | 0x02)
-#define CCR_RXDISABLE (CCR_CHANCTRL | 0x01)
-
-#define CCR_SENDSCHR1 (CCR_SENDCH | 0x01)
-#define CCR_SENDSCHR2 (CCR_SENDCH | 0x02)
-#define CCR_SENDSCHR3 (CCR_SENDCH | 0x03)
-#define CCR_SENDSCHR4 (CCR_SENDCH | 0x04)
-
-#define CCR_RESETCHAN (CCR_RESET | 0x00)
-#define CCR_RESETFULL (CCR_RESET | 0x01)
-#define CCR_TXFLUSHFIFO (CCR_RESET | 0x02)
-
-#define CCR_MAXWAIT 10000
-
-/*****************************************************************************/
-
-/*
- * Define the valid acknowledgement types (for hw ack cycle).
- */
-#define ACK_TYPMASK 0x07
-#define ACK_TYPTX 0x02
-#define ACK_TYPMDM 0x01
-#define ACK_TYPRXGOOD 0x03
-#define ACK_TYPRXBAD 0x07
-
-#define SVRR_RX 0x01
-#define SVRR_TX 0x02
-#define SVRR_MDM 0x04
-
-#define ST_OVERRUN 0x01
-#define ST_FRAMING 0x02
-#define ST_PARITY 0x04
-#define ST_BREAK 0x08
-#define ST_SCHAR1 0x10
-#define ST_SCHAR2 0x20
-#define ST_SCHAR3 0x30
-#define ST_SCHAR4 0x40
-#define ST_RANGE 0x70
-#define ST_SCHARMASK 0x70
-#define ST_TIMEOUT 0x80
-
-#define MISR_DCD 0x80
-#define MISR_CTS 0x40
-#define MISR_RI 0x20
-#define MISR_DSR 0x10
-
-/*****************************************************************************/
-
-/*
- * Defines for the CCSR status register.
- */
-#define CCSR_RXENABLED 0x80
-#define CCSR_RXFLOWON 0x40
-#define CCSR_RXFLOWOFF 0x20
-#define CCSR_TXENABLED 0x08
-#define CCSR_TXFLOWON 0x04
-#define CCSR_TXFLOWOFF 0x02
-
-/*****************************************************************************/
-
-/*
- * Define the embedded commands.
- */
-#define ETC_CMD 0x00
-#define ETC_STARTBREAK 0x81
-#define ETC_DELAY 0x82
-#define ETC_STOPBREAK 0x83
-
-/*****************************************************************************/
-#endif
diff --git a/include/linux/cdk.h b/include/linux/cdk.h
deleted file mode 100644
index 80093a8d4f64..000000000000
--- a/include/linux/cdk.h
+++ /dev/null
@@ -1,486 +0,0 @@
-/*****************************************************************************/
-
-/*
- * cdk.h -- CDK interface definitions.
- *
- * Copyright (C) 1996-1998 Stallion Technologies
- * Copyright (C) 1994-1996 Greg Ungerer.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*****************************************************************************/
-#ifndef _CDK_H
-#define _CDK_H
-/*****************************************************************************/
-
-#pragma pack(2)
-
-/*
- * The following set of definitions is used to communicate with the
- * shared memory interface of the Stallion intelligent multiport serial
- * boards. The definitions in this file are taken directly from the
- * document titled "Generic Stackable Interface, Downloader and
- * Communications Development Kit".
- */
-
-/*
- * Define the set of important shared memory addresses. These are
- * required to initialize the board and get things started. All of these
- * addresses are relative to the start of the shared memory.
- */
-#define CDK_SIGADDR 0x200
-#define CDK_FEATADDR 0x280
-#define CDK_CDKADDR 0x300
-#define CDK_RDYADDR 0x262
-
-#define CDK_ALIVEMARKER 13
-
-/*
- * On hardware power up the ROMs located on the EasyConnection 8/64 will
- * fill out the following signature information into shared memory. This
- * way the host system can quickly determine that the board is present
- * and is operational.
- */
-typedef struct cdkecpsig {
- unsigned long magic;
- unsigned short romver;
- unsigned short cputype;
- unsigned char panelid[8];
-} cdkecpsig_t;
-
-#define ECP_MAGIC 0x21504345
-
-/*
- * On hardware power up the ROMs located on the ONboard, Stallion and
- * Brumbys will fill out the following signature information into shared
- * memory. This way the host system can quickly determine that the board
- * is present and is operational.
- */
-typedef struct cdkonbsig {
- unsigned short magic0;
- unsigned short magic1;
- unsigned short magic2;
- unsigned short magic3;
- unsigned short romver;
- unsigned short memoff;
- unsigned short memseg;
- unsigned short amask0;
- unsigned short pic;
- unsigned short status;
- unsigned short btype;
- unsigned short clkticks;
- unsigned short clkspeed;
- unsigned short amask1;
- unsigned short amask2;
-} cdkonbsig_t;
-
-#define ONB_MAGIC0 0xf2a7
-#define ONB_MAGIC1 0xa149
-#define ONB_MAGIC2 0x6352
-#define ONB_MAGIC3 0xf121
-
-/*
- * Define the feature area structure. The feature area is the set of
- * startup parameters used by the slave image when it starts executing.
- * They allow for the specification of buffer sizes, debug trace, etc.
- */
-typedef struct cdkfeature {
- unsigned long debug;
- unsigned long banner;
- unsigned long etype;
- unsigned long nrdevs;
- unsigned long brdspec;
- unsigned long txrqsize;
- unsigned long rxrqsize;
- unsigned long flags;
-} cdkfeature_t;
-
-#define ETYP_DDK 0
-#define ETYP_CDK 1
-
-/*
- * Define the CDK header structure. This is the info that the slave
- * environment sets up after it has been downloaded and started. It
- * essentially provides a memory map for the shared memory interface.
- */
-typedef struct cdkhdr {
- unsigned short command;
- unsigned short status;
- unsigned short port;
- unsigned short mode;
- unsigned long cmd_buf[14];
- unsigned short alive_cnt;
- unsigned short intrpt_mode;
- unsigned char intrpt_id[8];
- unsigned char ver_release;
- unsigned char ver_modification;
- unsigned char ver_fix;
- unsigned char deadman_restart;
- unsigned short deadman;
- unsigned short nrdevs;
- unsigned long memp;
- unsigned long hostp;
- unsigned long slavep;
- unsigned char hostreq;
- unsigned char slavereq;
- unsigned char cmd_reserved[30];
-} cdkhdr_t;
-
-#define MODE_DDK 0
-#define MODE_CDK 1
-
-#define IMD_INTR 0x0
-#define IMD_PPINTR 0x1
-#define IMD_POLL 0xff
-
-/*
- * Define the memory mapping structure. This structure is pointed to by
- * the memp field in the stlcdkhdr struct. As many as these structures
- * as required are laid out in shared memory to define how the rest of
- * shared memory is divided up. There will be one for each port.
- */
-typedef struct cdkmem {
- unsigned short dtype;
- unsigned long offset;
-} cdkmem_t;
-
-#define TYP_UNDEFINED 0x0
-#define TYP_ASYNCTRL 0x1
-#define TYP_ASYNC 0x20
-#define TYP_PARALLEL 0x40
-#define TYP_SYNCX21 0x60
-
-/*****************************************************************************/
-
-/*
- * Following is a set of defines and structures used to actually deal
- * with the serial ports on the board. Firstly is the set of commands
- * that can be applied to ports.
- */
-#define ASYCMD (((unsigned long) 'a') << 8)
-
-#define A_NULL (ASYCMD | 0)
-#define A_FLUSH (ASYCMD | 1)
-#define A_BREAK (ASYCMD | 2)
-#define A_GETPORT (ASYCMD | 3)
-#define A_SETPORT (ASYCMD | 4)
-#define A_SETPORTF (ASYCMD | 5)
-#define A_SETPORTFTX (ASYCMD | 6)
-#define A_SETPORTFRX (ASYCMD | 7)
-#define A_GETSIGNALS (ASYCMD | 8)
-#define A_SETSIGNALS (ASYCMD | 9)
-#define A_SETSIGNALSF (ASYCMD | 10)
-#define A_SETSIGNALSFTX (ASYCMD | 11)
-#define A_SETSIGNALSFRX (ASYCMD | 12)
-#define A_GETNOTIFY (ASYCMD | 13)
-#define A_SETNOTIFY (ASYCMD | 14)
-#define A_NOTIFY (ASYCMD | 15)
-#define A_PORTCTRL (ASYCMD | 16)
-#define A_GETSTATS (ASYCMD | 17)
-#define A_RQSTATE (ASYCMD | 18)
-#define A_FLOWSTATE (ASYCMD | 19)
-#define A_CLEARSTATS (ASYCMD | 20)
-
-/*
- * Define those arguments used for simple commands.
- */
-#define FLUSHRX 0x1
-#define FLUSHTX 0x2
-
-#define BREAKON -1
-#define BREAKOFF -2
-
-/*
- * Define the port setting structure, and all those defines that go along
- * with it. Basically this structure defines the characteristics of this
- * port: baud rate, chars, parity, input/output char cooking etc.
- */
-typedef struct asyport {
- unsigned long baudout;
- unsigned long baudin;
- unsigned long iflag;
- unsigned long oflag;
- unsigned long lflag;
- unsigned long pflag;
- unsigned long flow;
- unsigned long spare1;
- unsigned short vtime;
- unsigned short vmin;
- unsigned short txlo;
- unsigned short txhi;
- unsigned short rxlo;
- unsigned short rxhi;
- unsigned short rxhog;
- unsigned short spare2;
- unsigned char csize;
- unsigned char stopbs;
- unsigned char parity;
- unsigned char stopin;
- unsigned char startin;
- unsigned char stopout;
- unsigned char startout;
- unsigned char parmark;
- unsigned char brkmark;
- unsigned char cc[11];
-} asyport_t;
-
-#define PT_STOP1 0x0
-#define PT_STOP15 0x1
-#define PT_STOP2 0x2
-
-#define PT_NOPARITY 0x0
-#define PT_ODDPARITY 0x1
-#define PT_EVENPARITY 0x2
-#define PT_MARKPARITY 0x3
-#define PT_SPACEPARITY 0x4
-
-#define F_NONE 0x0
-#define F_IXON 0x1
-#define F_IXOFF 0x2
-#define F_IXANY 0x4
-#define F_IOXANY 0x8
-#define F_RTSFLOW 0x10
-#define F_CTSFLOW 0x20
-#define F_DTRFLOW 0x40
-#define F_DCDFLOW 0x80
-#define F_DSROFLOW 0x100
-#define F_DSRIFLOW 0x200
-
-#define FI_NORX 0x1
-#define FI_RAW 0x2
-#define FI_ISTRIP 0x4
-#define FI_UCLC 0x8
-#define FI_INLCR 0x10
-#define FI_ICRNL 0x20
-#define FI_IGNCR 0x40
-#define FI_IGNBREAK 0x80
-#define FI_DSCRDBREAK 0x100
-#define FI_1MARKBREAK 0x200
-#define FI_2MARKBREAK 0x400
-#define FI_XCHNGBREAK 0x800
-#define FI_IGNRXERRS 0x1000
-#define FI_DSCDRXERRS 0x2000
-#define FI_1MARKRXERRS 0x4000
-#define FI_2MARKRXERRS 0x8000
-#define FI_XCHNGRXERRS 0x10000
-#define FI_DSCRDNULL 0x20000
-
-#define FO_OLCUC 0x1
-#define FO_ONLCR 0x2
-#define FO_OOCRNL 0x4
-#define FO_ONOCR 0x8
-#define FO_ONLRET 0x10
-#define FO_ONL 0x20
-#define FO_OBS 0x40
-#define FO_OVT 0x80
-#define FO_OFF 0x100
-#define FO_OTAB1 0x200
-#define FO_OTAB2 0x400
-#define FO_OTAB3 0x800
-#define FO_OCR1 0x1000
-#define FO_OCR2 0x2000
-#define FO_OCR3 0x4000
-#define FO_OFILL 0x8000
-#define FO_ODELL 0x10000
-
-#define P_RTSLOCK 0x1
-#define P_CTSLOCK 0x2
-#define P_MAPRTS 0x4
-#define P_MAPCTS 0x8
-#define P_LOOPBACK 0x10
-#define P_DTRFOLLOW 0x20
-#define P_FAKEDCD 0x40
-
-#define P_RXIMIN 0x10000
-#define P_RXITIME 0x20000
-#define P_RXTHOLD 0x40000
-
-/*
- * Define a structure to communicate serial port signal and data state
- * information.
- */
-typedef struct asysigs {
- unsigned long data;
- unsigned long signal;
- unsigned long sigvalue;
-} asysigs_t;
-
-#define DT_TXBUSY 0x1
-#define DT_TXEMPTY 0x2
-#define DT_TXLOW 0x4
-#define DT_TXHIGH 0x8
-#define DT_TXFULL 0x10
-#define DT_TXHOG 0x20
-#define DT_TXFLOWED 0x40
-#define DT_TXBREAK 0x80
-
-#define DT_RXBUSY 0x100
-#define DT_RXEMPTY 0x200
-#define DT_RXLOW 0x400
-#define DT_RXHIGH 0x800
-#define DT_RXFULL 0x1000
-#define DT_RXHOG 0x2000
-#define DT_RXFLOWED 0x4000
-#define DT_RXBREAK 0x8000
-
-#define SG_DTR 0x1
-#define SG_DCD 0x2
-#define SG_RTS 0x4
-#define SG_CTS 0x8
-#define SG_DSR 0x10
-#define SG_RI 0x20
-
-/*
- * Define the notification setting structure. This is used to tell the
- * port what events we want to be informed about. Fields here use the
- * same defines as for the asysigs structure above.
- */
-typedef struct asynotify {
- unsigned long ctrl;
- unsigned long data;
- unsigned long signal;
- unsigned long sigvalue;
-} asynotify_t;
-
-/*
- * Define the port control structure. It is used to do fine grain
- * control operations on the port.
- */
-typedef struct {
- unsigned long rxctrl;
- unsigned long txctrl;
- char rximdch;
- char tximdch;
- char spare1;
- char spare2;
-} asyctrl_t;
-
-#define CT_ENABLE 0x1
-#define CT_DISABLE 0x2
-#define CT_STOP 0x4
-#define CT_START 0x8
-#define CT_STARTFLOW 0x10
-#define CT_STOPFLOW 0x20
-#define CT_SENDCHR 0x40
-
-/*
- * Define the stats structure kept for each port. This is a useful set
- * of data collected for each port on the slave. The A_GETSTATS command
- * is used to retrieve this data from the slave.
- */
-typedef struct asystats {
- unsigned long opens;
- unsigned long txchars;
- unsigned long rxchars;
- unsigned long txringq;
- unsigned long rxringq;
- unsigned long txmsgs;
- unsigned long rxmsgs;
- unsigned long txflushes;
- unsigned long rxflushes;
- unsigned long overruns;
- unsigned long framing;
- unsigned long parity;
- unsigned long ringover;
- unsigned long lost;
- unsigned long rxstart;
- unsigned long rxstop;
- unsigned long txstart;
- unsigned long txstop;
- unsigned long dcdcnt;
- unsigned long dtrcnt;
- unsigned long ctscnt;
- unsigned long rtscnt;
- unsigned long dsrcnt;
- unsigned long ricnt;
- unsigned long txbreaks;
- unsigned long rxbreaks;
- unsigned long signals;
- unsigned long state;
- unsigned long hwid;
-} asystats_t;
-
-/*****************************************************************************/
-
-/*
- * All command and control communication with a device on the slave is
- * via a control block in shared memory. Each device has its own control
- * block, defined by the following structure. The control block allows
- * the host to open, close and control the device on the slave.
- */
-typedef struct cdkctrl {
- unsigned char open;
- unsigned char close;
- unsigned long openarg;
- unsigned long closearg;
- unsigned long cmd;
- unsigned long status;
- unsigned long args[32];
-} cdkctrl_t;
-
-/*
- * Each device on the slave passes data to and from the host via a ring
- * queue in shared memory. Define a ring queue structure to hold the
- * vital information about each ring queue. Two ring queues will be
- * allocated for each port, one for receive data and one for transmit
- * data.
- */
-typedef struct cdkasyrq {
- unsigned long offset;
- unsigned short size;
- unsigned short head;
- unsigned short tail;
-} cdkasyrq_t;
-
-/*
- * Each asynchronous port is defined in shared memory by the following
- * structure. It contains a control block to command a device, and also
- * the necessary data channel information as well.
- */
-typedef struct cdkasy {
- cdkctrl_t ctrl;
- unsigned short notify;
- asynotify_t changed;
- unsigned short receive;
- cdkasyrq_t rxq;
- unsigned short transmit;
- cdkasyrq_t txq;
-} cdkasy_t;
-
-#pragma pack()
-
-/*****************************************************************************/
-
-/*
- * Define the set of ioctls used by the driver to do special things
- * to the board. These include interrupting it, and initializing
- * the driver after board startup and shutdown.
- */
-#include <linux/ioctl.h>
-
-#define STL_BINTR _IO('s',20)
-#define STL_BSTART _IO('s',21)
-#define STL_BSTOP _IO('s',22)
-#define STL_BRESET _IO('s',23)
-
-/*
- * Define a set of ioctl extensions, used to get at special stuff.
- */
-#define STL_GETPFLAG _IO('s',80)
-#define STL_SETPFLAG _IO('s',81)
-
-/*****************************************************************************/
-#endif
diff --git a/include/linux/comstats.h b/include/linux/comstats.h
deleted file mode 100644
index 3f5ea8e8026d..000000000000
--- a/include/linux/comstats.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*****************************************************************************/
-
-/*
- * comstats.h -- Serial Port Stats.
- *
- * Copyright (C) 1996-1998 Stallion Technologies
- * Copyright (C) 1994-1996 Greg Ungerer.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*****************************************************************************/
-#ifndef _COMSTATS_H
-#define _COMSTATS_H
-/*****************************************************************************/
-
-/*
- * Serial port stats structure. The structure itself is UART
- * independent, but some fields may be UART/driver specific (for
- * example state).
- */
-
-typedef struct {
- unsigned long brd;
- unsigned long panel;
- unsigned long port;
- unsigned long hwid;
- unsigned long type;
- unsigned long txtotal;
- unsigned long rxtotal;
- unsigned long txbuffered;
- unsigned long rxbuffered;
- unsigned long rxoverrun;
- unsigned long rxparity;
- unsigned long rxframing;
- unsigned long rxlost;
- unsigned long txbreaks;
- unsigned long rxbreaks;
- unsigned long txxon;
- unsigned long txxoff;
- unsigned long rxxon;
- unsigned long rxxoff;
- unsigned long txctson;
- unsigned long txctsoff;
- unsigned long rxrtson;
- unsigned long rxrtsoff;
- unsigned long modem;
- unsigned long state;
- unsigned long flags;
- unsigned long ttystate;
- unsigned long cflags;
- unsigned long iflags;
- unsigned long oflags;
- unsigned long lflags;
- unsigned long signals;
-} comstats_t;
-
-
-/*
- * Board stats structure. Returns useful info about the board.
- */
-
-#define COM_MAXPANELS 8
-
-typedef struct {
- unsigned long panel;
- unsigned long type;
- unsigned long hwid;
- unsigned long nrports;
-} companel_t;
-
-typedef struct {
- unsigned long brd;
- unsigned long type;
- unsigned long hwid;
- unsigned long state;
- unsigned long ioaddr;
- unsigned long ioaddr2;
- unsigned long memaddr;
- unsigned long irq;
- unsigned long nrpanels;
- unsigned long nrports;
- companel_t panels[COM_MAXPANELS];
-} combrd_t;
-
-
-/*
- * Define the ioctl operations for stats stuff.
- */
-#include <linux/ioctl.h>
-
-#define COM_GETPORTSTATS _IO('c',30)
-#define COM_CLRPORTSTATS _IO('c',31)
-#define COM_GETBRDSTATS _IO('c',32)
-
-
-/*
- * Define the set of ioctls that give user level access to the
- * private port, panel and board structures. The argument required
- * will be driver dependent!
- */
-#define COM_READPORT _IO('c',40)
-#define COM_READBOARD _IO('c',41)
-#define COM_READPANEL _IO('c',42)
-
-/*****************************************************************************/
-#endif
diff --git a/include/linux/generic_serial.h b/include/linux/generic_serial.h
deleted file mode 100644
index 79b3eb37243a..000000000000
--- a/include/linux/generic_serial.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * generic_serial.h
- *
- * Copyright (C) 1998 R.E.Wolff@BitWizard.nl
- *
- * written for the SX serial driver.
- *
- * Version 0.1 -- December, 1998.
- */
-
-#ifndef GENERIC_SERIAL_H
-#define GENERIC_SERIAL_H
-
-#warning Use of this header is deprecated.
-#warning Since nobody sets the constants defined here for you, you should not, in any case, use them. Including the header is thus pointless.
-
-/* Flags */
-/* Warning: serial.h defines some ASYNC_ flags, they say they are "only"
- used in serial.c, but they are also used in all other serial drivers.
- Make sure they don't clash with these here... */
-#define GS_TX_INTEN 0x00800000
-#define GS_RX_INTEN 0x00400000
-#define GS_ACTIVE 0x00200000
-
-#define GS_TYPE_NORMAL 1
-
-#define GS_DEBUG_FLUSH 0x00000001
-#define GS_DEBUG_BTR 0x00000002
-#define GS_DEBUG_TERMIOS 0x00000004
-#define GS_DEBUG_STUFF 0x00000008
-#define GS_DEBUG_CLOSE 0x00000010
-#define GS_DEBUG_FLOW 0x00000020
-#define GS_DEBUG_WRITE 0x00000040
-
-#endif
diff --git a/include/linux/istallion.h b/include/linux/istallion.h
deleted file mode 100644
index ad700a60c158..000000000000
--- a/include/linux/istallion.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*****************************************************************************/
-
-/*
- * istallion.h -- stallion intelligent multiport serial driver.
- *
- * Copyright (C) 1996-1998 Stallion Technologies
- * Copyright (C) 1994-1996 Greg Ungerer.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*****************************************************************************/
-#ifndef _ISTALLION_H
-#define _ISTALLION_H
-/*****************************************************************************/
-
-/*
- * Define important driver constants here.
- */
-#define STL_MAXBRDS 4
-#define STL_MAXPANELS 4
-#define STL_MAXPORTS 64
-#define STL_MAXCHANS (STL_MAXPORTS + 1)
-#define STL_MAXDEVS (STL_MAXBRDS * STL_MAXPORTS)
-
-
-/*
- * Define a set of structures to hold all the board/panel/port info
- * for our ports. These will be dynamically allocated as required at
- * driver initialization time.
- */
-
-/*
- * Port and board structures to hold status info about each object.
- * The board structure contains pointers to structures for each port
- * connected to it. Panels are not distinguished here, since
- * communication with the slave board will always be on a per port
- * basis.
- */
-struct stliport {
- unsigned long magic;
- struct tty_port port;
- unsigned int portnr;
- unsigned int panelnr;
- unsigned int brdnr;
- unsigned long state;
- unsigned int devnr;
- int baud_base;
- int custom_divisor;
- int closing_wait;
- int rc;
- int argsize;
- void *argp;
- unsigned int rxmarkmsk;
- wait_queue_head_t raw_wait;
- struct asysigs asig;
- unsigned long addr;
- unsigned long rxoffset;
- unsigned long txoffset;
- unsigned long sigs;
- unsigned long pflag;
- unsigned int rxsize;
- unsigned int txsize;
- unsigned char reqbit;
- unsigned char portidx;
- unsigned char portbit;
-};
-
-/*
- * Use a structure of function pointers to do board level operations.
- * These include, enable/disable, paging shared memory, interrupting, etc.
- */
-struct stlibrd {
- unsigned long magic;
- unsigned int brdnr;
- unsigned int brdtype;
- unsigned long state;
- unsigned int nrpanels;
- unsigned int nrports;
- unsigned int nrdevs;
- unsigned int iobase;
- int iosize;
- unsigned long memaddr;
- void __iomem *membase;
- unsigned long memsize;
- int pagesize;
- int hostoffset;
- int slaveoffset;
- int bitsize;
- int enabval;
- unsigned int panels[STL_MAXPANELS];
- int panelids[STL_MAXPANELS];
- void (*init)(struct stlibrd *brdp);
- void (*enable)(struct stlibrd *brdp);
- void (*reenable)(struct stlibrd *brdp);
- void (*disable)(struct stlibrd *brdp);
- void __iomem *(*getmemptr)(struct stlibrd *brdp, unsigned long offset, int line);
- void (*intr)(struct stlibrd *brdp);
- void (*reset)(struct stlibrd *brdp);
- struct stliport *ports[STL_MAXPORTS];
-};
-
-
-/*
- * Define MAGIC numbers used for above structures.
- */
-#define STLI_PORTMAGIC 0xe671c7a1
-#define STLI_BOARDMAGIC 0x4bc6c825
-
-/*****************************************************************************/
-#endif
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index daf4a3a40ee0..af9137db3035 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -145,16 +145,4 @@ void compute_shiftstate(void);
extern unsigned int keymap_count;
-/* console.c */
-
-static inline void con_schedule_flip(struct tty_struct *t)
-{
- unsigned long flags;
- spin_lock_irqsave(&t->buf.lock, flags);
- if (t->buf.tail != NULL)
- t->buf.tail->commit = t->buf.tail->used;
- spin_unlock_irqrestore(&t->buf.lock, flags);
- schedule_work(&t->buf.work);
-}
-
#endif
diff --git a/include/linux/sc26198.h b/include/linux/sc26198.h
deleted file mode 100644
index 7ca35abad387..000000000000
--- a/include/linux/sc26198.h
+++ /dev/null
@@ -1,533 +0,0 @@
-/*****************************************************************************/
-
-/*
- * sc26198.h -- SC26198 UART hardware info.
- *
- * Copyright (C) 1995-1998 Stallion Technologies
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*****************************************************************************/
-#ifndef _SC26198_H
-#define _SC26198_H
-/*****************************************************************************/
-
-/*
- * Define the number of async ports per sc26198 uart device.
- */
-#define SC26198_PORTS 8
-
-/*
- * Baud rate timing clocks. All derived from a master 14.7456 MHz clock.
- */
-#define SC26198_MASTERCLOCK 14745600L
-#define SC26198_DCLK (SC26198_MASTERCLOCK)
-#define SC26198_CCLK (SC26198_MASTERCLOCK / 2)
-#define SC26198_BCLK (SC26198_MASTERCLOCK / 4)
-
-/*
- * Define internal FIFO sizes for the 26198 ports.
- */
-#define SC26198_TXFIFOSIZE 16
-#define SC26198_RXFIFOSIZE 16
-
-/*****************************************************************************/
-
-/*
- * Global register definitions. These registers are global to each 26198
- * device, not specific ports on it.
- */
-#define TSTR 0x0d
-#define GCCR 0x0f
-#define ICR 0x1b
-#define WDTRCR 0x1d
-#define IVR 0x1f
-#define BRGTRUA 0x84
-#define GPOSR 0x87
-#define GPOC 0x8b
-#define UCIR 0x8c
-#define CIR 0x8c
-#define BRGTRUB 0x8d
-#define GRXFIFO 0x8e
-#define GTXFIFO 0x8e
-#define GCCR2 0x8f
-#define BRGTRLA 0x94
-#define GPOR 0x97
-#define GPOD 0x9b
-#define BRGTCR 0x9c
-#define GICR 0x9c
-#define BRGTRLB 0x9d
-#define GIBCR 0x9d
-#define GITR 0x9f
-
-/*
- * Per port channel registers. These are the register offsets within
- * the port address space, so need to have the port address (0 to 7)
- * inserted in bit positions 4:6.
- */
-#define MR0 0x00
-#define MR1 0x01
-#define IOPCR 0x02
-#define BCRBRK 0x03
-#define BCRCOS 0x04
-#define BCRX 0x06
-#define BCRA 0x07
-#define XONCR 0x08
-#define XOFFCR 0x09
-#define ARCR 0x0a
-#define RXCSR 0x0c
-#define TXCSR 0x0e
-#define MR2 0x80
-#define SR 0x81
-#define SCCR 0x81
-#define ISR 0x82
-#define IMR 0x82
-#define TXFIFO 0x83
-#define RXFIFO 0x83
-#define IPR 0x84
-#define IOPIOR 0x85
-#define XISR 0x86
-
-/*
- * For any given port calculate the address to use to access a specified
- * register. This is only used for unusual access, mostly this is done
- * through the assembler access routines.
- */
-#define SC26198_PORTREG(port,reg) ((((port) & 0x07) << 4) | (reg))
-
-/*****************************************************************************/
-
-/*
- * Global configuration control register bit definitions.
- */
-#define GCCR_NOACK 0x00
-#define GCCR_IVRACK 0x02
-#define GCCR_IVRCHANACK 0x04
-#define GCCR_IVRTYPCHANACK 0x06
-#define GCCR_ASYNCCYCLE 0x00
-#define GCCR_SYNCCYCLE 0x40
-
-/*****************************************************************************/
-
-/*
- * Mode register 0 bit definitions.
- */
-#define MR0_ADDRNONE 0x00
-#define MR0_AUTOWAKE 0x01
-#define MR0_AUTODOZE 0x02
-#define MR0_AUTOWAKEDOZE 0x03
-#define MR0_SWFNONE 0x00
-#define MR0_SWFTX 0x04
-#define MR0_SWFRX 0x08
-#define MR0_SWFRXTX 0x0c
-#define MR0_TXMASK 0x30
-#define MR0_TXEMPTY 0x00
-#define MR0_TXHIGH 0x10
-#define MR0_TXHALF 0x20
-#define MR0_TXRDY 0x00
-#define MR0_ADDRNT 0x00
-#define MR0_ADDRT 0x40
-#define MR0_SWFNT 0x00
-#define MR0_SWFT 0x80
-
-/*
- * Mode register 1 bit definitions.
- */
-#define MR1_CS5 0x00
-#define MR1_CS6 0x01
-#define MR1_CS7 0x02
-#define MR1_CS8 0x03
-#define MR1_PAREVEN 0x00
-#define MR1_PARODD 0x04
-#define MR1_PARENB 0x00
-#define MR1_PARFORCE 0x08
-#define MR1_PARNONE 0x10
-#define MR1_PARSPECIAL 0x18
-#define MR1_ERRCHAR 0x00
-#define MR1_ERRBLOCK 0x20
-#define MR1_ISRUNMASKED 0x00
-#define MR1_ISRMASKED 0x40
-#define MR1_AUTORTS 0x80
-
-/*
- * Mode register 2 bit definitions.
- */
-#define MR2_STOP1 0x00
-#define MR2_STOP15 0x01
-#define MR2_STOP2 0x02
-#define MR2_STOP916 0x03
-#define MR2_RXFIFORDY 0x00
-#define MR2_RXFIFOHALF 0x04
-#define MR2_RXFIFOHIGH 0x08
-#define MR2_RXFIFOFULL 0x0c
-#define MR2_AUTOCTS 0x10
-#define MR2_TXRTS 0x20
-#define MR2_MODENORM 0x00
-#define MR2_MODEAUTOECHO 0x40
-#define MR2_MODELOOP 0x80
-#define MR2_MODEREMECHO 0xc0
-
-/*****************************************************************************/
-
-/*
- * Baud Rate Generator (BRG) selector values.
- */
-#define BRG_50 0x00
-#define BRG_75 0x01
-#define BRG_150 0x02
-#define BRG_200 0x03
-#define BRG_300 0x04
-#define BRG_450 0x05
-#define BRG_600 0x06
-#define BRG_900 0x07
-#define BRG_1200 0x08
-#define BRG_1800 0x09
-#define BRG_2400 0x0a
-#define BRG_3600 0x0b
-#define BRG_4800 0x0c
-#define BRG_7200 0x0d
-#define BRG_9600 0x0e
-#define BRG_14400 0x0f
-#define BRG_19200 0x10
-#define BRG_28200 0x11
-#define BRG_38400 0x12
-#define BRG_57600 0x13
-#define BRG_115200 0x14
-#define BRG_230400 0x15
-#define BRG_GIN0 0x16
-#define BRG_GIN1 0x17
-#define BRG_CT0 0x18
-#define BRG_CT1 0x19
-#define BRG_RX2TX316 0x1b
-#define BRG_RX2TX31 0x1c
-
-#define SC26198_MAXBAUD 921600
-
-/*****************************************************************************/
-
-/*
- * Command register command definitions.
- */
-#define CR_NULL 0x04
-#define CR_ADDRNORMAL 0x0c
-#define CR_RXRESET 0x14
-#define CR_TXRESET 0x1c
-#define CR_CLEARRXERR 0x24
-#define CR_BREAKRESET 0x2c
-#define CR_TXSTARTBREAK 0x34
-#define CR_TXSTOPBREAK 0x3c
-#define CR_RTSON 0x44
-#define CR_RTSOFF 0x4c
-#define CR_ADDRINIT 0x5c
-#define CR_RXERRBLOCK 0x6c
-#define CR_TXSENDXON 0x84
-#define CR_TXSENDXOFF 0x8c
-#define CR_GANGXONSET 0x94
-#define CR_GANGXOFFSET 0x9c
-#define CR_GANGXONINIT 0xa4
-#define CR_GANGXOFFINIT 0xac
-#define CR_HOSTXON 0xb4
-#define CR_HOSTXOFF 0xbc
-#define CR_CANCELXOFF 0xc4
-#define CR_ADDRRESET 0xdc
-#define CR_RESETALLPORTS 0xf4
-#define CR_RESETALL 0xfc
-
-#define CR_RXENABLE 0x01
-#define CR_TXENABLE 0x02
-
-/*****************************************************************************/
-
-/*
- * Channel status register.
- */
-#define SR_RXRDY 0x01
-#define SR_RXFULL 0x02
-#define SR_TXRDY 0x04
-#define SR_TXEMPTY 0x08
-#define SR_RXOVERRUN 0x10
-#define SR_RXPARITY 0x20
-#define SR_RXFRAMING 0x40
-#define SR_RXBREAK 0x80
-
-#define SR_RXERRS (SR_RXPARITY | SR_RXFRAMING | SR_RXOVERRUN)
-
-/*****************************************************************************/
-
-/*
- * Interrupt status register and interrupt mask register bit definitions.
- */
-#define IR_TXRDY 0x01
-#define IR_RXRDY 0x02
-#define IR_RXBREAK 0x04
-#define IR_XONXOFF 0x10
-#define IR_ADDRRECOG 0x20
-#define IR_RXWATCHDOG 0x40
-#define IR_IOPORT 0x80
-
-/*****************************************************************************/
-
-/*
- * Interrupt vector register field definitions.
- */
-#define IVR_CHANMASK 0x07
-#define IVR_TYPEMASK 0x18
-#define IVR_CONSTMASK 0xc0
-
-#define IVR_RXDATA 0x10
-#define IVR_RXBADDATA 0x18
-#define IVR_TXDATA 0x08
-#define IVR_OTHER 0x00
-
-/*****************************************************************************/
-
-/*
- * BRG timer control register bit definitions.
- */
-#define BRGCTCR_DISABCLK0 0x00
-#define BRGCTCR_ENABCLK0 0x08
-#define BRGCTCR_DISABCLK1 0x00
-#define BRGCTCR_ENABCLK1 0x80
-
-#define BRGCTCR_0SCLK16 0x00
-#define BRGCTCR_0SCLK32 0x01
-#define BRGCTCR_0SCLK64 0x02
-#define BRGCTCR_0SCLK128 0x03
-#define BRGCTCR_0X1 0x04
-#define BRGCTCR_0X12 0x05
-#define BRGCTCR_0IO1A 0x06
-#define BRGCTCR_0GIN0 0x07
-
-#define BRGCTCR_1SCLK16 0x00
-#define BRGCTCR_1SCLK32 0x10
-#define BRGCTCR_1SCLK64 0x20
-#define BRGCTCR_1SCLK128 0x30
-#define BRGCTCR_1X1 0x40
-#define BRGCTCR_1X12 0x50
-#define BRGCTCR_1IO1B 0x60
-#define BRGCTCR_1GIN1 0x70
-
-/*****************************************************************************/
-
-/*
- * Watch dog timer enable register.
- */
-#define WDTRCR_ENABALL 0xff
-
-/*****************************************************************************/
-
-/*
- * XON/XOFF interrupt status register.
- */
-#define XISR_TXCHARMASK 0x03
-#define XISR_TXCHARNORMAL 0x00
-#define XISR_TXWAIT 0x01
-#define XISR_TXXOFFPEND 0x02
-#define XISR_TXXONPEND 0x03
-
-#define XISR_TXFLOWMASK 0x0c
-#define XISR_TXNORMAL 0x00
-#define XISR_TXSTOPPEND 0x04
-#define XISR_TXSTARTED 0x08
-#define XISR_TXSTOPPED 0x0c
-
-#define XISR_RXFLOWMASK 0x30
-#define XISR_RXFLOWNONE 0x00
-#define XISR_RXXONSENT 0x10
-#define XISR_RXXOFFSENT 0x20
-
-#define XISR_RXXONGOT 0x40
-#define XISR_RXXOFFGOT 0x80
-
-/*****************************************************************************/
-
-/*
- * Current interrupt register.
- */
-#define CIR_TYPEMASK 0xc0
-#define CIR_TYPEOTHER 0x00
-#define CIR_TYPETX 0x40
-#define CIR_TYPERXGOOD 0x80
-#define CIR_TYPERXBAD 0xc0
-
-#define CIR_RXDATA 0x80
-#define CIR_RXBADDATA 0x40
-#define CIR_TXDATA 0x40
-
-#define CIR_CHANMASK 0x07
-#define CIR_CNTMASK 0x38
-
-#define CIR_SUBTYPEMASK 0x38
-#define CIR_SUBNONE 0x00
-#define CIR_SUBCOS 0x08
-#define CIR_SUBADDR 0x10
-#define CIR_SUBXONXOFF 0x18
-#define CIR_SUBBREAK 0x28
-
-/*****************************************************************************/
-
-/*
- * Global interrupting channel register.
- */
-#define GICR_CHANMASK 0x07
-
-/*****************************************************************************/
-
-/*
- * Global interrupting byte count register.
- */
-#define GICR_COUNTMASK 0x0f
-
-/*****************************************************************************/
-
-/*
- * Global interrupting type register.
- */
-#define GITR_RXMASK 0xc0
-#define GITR_RXNONE 0x00
-#define GITR_RXBADDATA 0x80
-#define GITR_RXGOODDATA 0xc0
-#define GITR_TXDATA 0x20
-
-#define GITR_SUBTYPEMASK 0x07
-#define GITR_SUBNONE 0x00
-#define GITR_SUBCOS 0x01
-#define GITR_SUBADDR 0x02
-#define GITR_SUBXONXOFF 0x03
-#define GITR_SUBBREAK 0x05
-
-/*****************************************************************************/
-
-/*
- * Input port change register.
- */
-#define IPR_CTS 0x01
-#define IPR_DTR 0x02
-#define IPR_RTS 0x04
-#define IPR_DCD 0x08
-#define IPR_CTSCHANGE 0x10
-#define IPR_DTRCHANGE 0x20
-#define IPR_RTSCHANGE 0x40
-#define IPR_DCDCHANGE 0x80
-
-#define IPR_CHANGEMASK 0xf0
-
-/*****************************************************************************/
-
-/*
- * IO port interrupt and output register.
- */
-#define IOPR_CTS 0x01
-#define IOPR_DTR 0x02
-#define IOPR_RTS 0x04
-#define IOPR_DCD 0x08
-#define IOPR_CTSCOS 0x10
-#define IOPR_DTRCOS 0x20
-#define IOPR_RTSCOS 0x40
-#define IOPR_DCDCOS 0x80
-
-/*****************************************************************************/
-
-/*
- * IO port configuration register.
- */
-#define IOPCR_SETCTS 0x00
-#define IOPCR_SETDTR 0x04
-#define IOPCR_SETRTS 0x10
-#define IOPCR_SETDCD 0x00
-
-#define IOPCR_SETSIGS (IOPCR_SETRTS | IOPCR_SETRTS | IOPCR_SETDTR | IOPCR_SETDCD)
-
-/*****************************************************************************/
-
-/*
- * General purpose output select register.
- */
-#define GPORS_TXC1XA 0x08
-#define GPORS_TXC16XA 0x09
-#define GPORS_RXC16XA 0x0a
-#define GPORS_TXC16XB 0x0b
-#define GPORS_GPOR3 0x0c
-#define GPORS_GPOR2 0x0d
-#define GPORS_GPOR1 0x0e
-#define GPORS_GPOR0 0x0f
-
-/*****************************************************************************/
-
-/*
- * General purpose output register.
- */
-#define GPOR_0 0x01
-#define GPOR_1 0x02
-#define GPOR_2 0x04
-#define GPOR_3 0x08
-
-/*****************************************************************************/
-
-/*
- * General purpose output clock register.
- */
-#define GPORC_0NONE 0x00
-#define GPORC_0GIN0 0x01
-#define GPORC_0GIN1 0x02
-#define GPORC_0IO3A 0x02
-
-#define GPORC_1NONE 0x00
-#define GPORC_1GIN0 0x04
-#define GPORC_1GIN1 0x08
-#define GPORC_1IO3C 0x0c
-
-#define GPORC_2NONE 0x00
-#define GPORC_2GIN0 0x10
-#define GPORC_2GIN1 0x20
-#define GPORC_2IO3E 0x20
-
-#define GPORC_3NONE 0x00
-#define GPORC_3GIN0 0x40
-#define GPORC_3GIN1 0x80
-#define GPORC_3IO3G 0xc0
-
-/*****************************************************************************/
-
-/*
- * General purpose output data register.
- */
-#define GPOD_0MASK 0x03
-#define GPOD_0SET1 0x00
-#define GPOD_0SET0 0x01
-#define GPOD_0SETR0 0x02
-#define GPOD_0SETIO3B 0x03
-
-#define GPOD_1MASK 0x0c
-#define GPOD_1SET1 0x00
-#define GPOD_1SET0 0x04
-#define GPOD_1SETR0 0x08
-#define GPOD_1SETIO3D 0x0c
-
-#define GPOD_2MASK 0x30
-#define GPOD_2SET1 0x00
-#define GPOD_2SET0 0x10
-#define GPOD_2SETR0 0x20
-#define GPOD_2SETIO3F 0x30
-
-#define GPOD_3MASK 0xc0
-#define GPOD_3SET1 0x00
-#define GPOD_3SET0 0x40
-#define GPOD_3SETR0 0x80
-#define GPOD_3SETIO3H 0xc0
-
-/*****************************************************************************/
-#endif
diff --git a/include/linux/serial167.h b/include/linux/serial167.h
deleted file mode 100644
index 59c81b708562..000000000000
--- a/include/linux/serial167.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * serial167.h
- *
- * Richard Hirst [richard@sleepie.demon.co.uk]
- *
- * Based on cyclades.h
- */
-
-struct cyclades_monitor {
- unsigned long int_count;
- unsigned long char_count;
- unsigned long char_max;
- unsigned long char_last;
-};
-
-/*
- * This is our internal structure for each serial port's state.
- *
- * Many fields are paralleled by the structure used by the serial_struct
- * structure.
- *
- * For definitions of the flags field, see tty.h
- */
-
-struct cyclades_port {
- int magic;
- int type;
- int card;
- int line;
- int flags; /* defined in tty.h */
- struct tty_struct *tty;
- int read_status_mask;
- int timeout;
- int xmit_fifo_size;
- int cor1,cor2,cor3,cor4,cor5,cor6,cor7;
- int tbpr,tco,rbpr,rco;
- int ignore_status_mask;
- int close_delay;
- int IER; /* Interrupt Enable Register */
- unsigned long last_active;
- int count; /* # of fd on device */
- int x_char; /* to be pushed out ASAP */
- int x_break;
- int blocked_open; /* # of blocked opens */
- unsigned char *xmit_buf;
- int xmit_head;
- int xmit_tail;
- int xmit_cnt;
- int default_threshold;
- int default_timeout;
- wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
- struct cyclades_monitor mon;
-};
-
-#define CYCLADES_MAGIC 0x4359
-
-#define CYGETMON 0x435901
-#define CYGETTHRESH 0x435902
-#define CYSETTHRESH 0x435903
-#define CYGETDEFTHRESH 0x435904
-#define CYSETDEFTHRESH 0x435905
-#define CYGETTIMEOUT 0x435906
-#define CYSETTIMEOUT 0x435907
-#define CYGETDEFTIMEOUT 0x435908
-#define CYSETDEFTIMEOUT 0x435909
-
-#define CyMaxChipsPerCard 1
-
-/**** cd2401 registers ****/
-
-#define CyGFRCR (0x81)
-#define CyCCR (0x13)
-#define CyCLR_CHAN (0x40)
-#define CyINIT_CHAN (0x20)
-#define CyCHIP_RESET (0x10)
-#define CyENB_XMTR (0x08)
-#define CyDIS_XMTR (0x04)
-#define CyENB_RCVR (0x02)
-#define CyDIS_RCVR (0x01)
-#define CyCAR (0xee)
-#define CyIER (0x11)
-#define CyMdmCh (0x80)
-#define CyRxExc (0x20)
-#define CyRxData (0x08)
-#define CyTxMpty (0x02)
-#define CyTxRdy (0x01)
-#define CyLICR (0x26)
-#define CyRISR (0x89)
-#define CyTIMEOUT (0x80)
-#define CySPECHAR (0x70)
-#define CyOVERRUN (0x08)
-#define CyPARITY (0x04)
-#define CyFRAME (0x02)
-#define CyBREAK (0x01)
-#define CyREOIR (0x84)
-#define CyTEOIR (0x85)
-#define CyMEOIR (0x86)
-#define CyNOTRANS (0x08)
-#define CyRFOC (0x30)
-#define CyRDR (0xf8)
-#define CyTDR (0xf8)
-#define CyMISR (0x8b)
-#define CyRISR (0x89)
-#define CyTISR (0x8a)
-#define CyMSVR1 (0xde)
-#define CyMSVR2 (0xdf)
-#define CyDSR (0x80)
-#define CyDCD (0x40)
-#define CyCTS (0x20)
-#define CyDTR (0x02)
-#define CyRTS (0x01)
-#define CyRTPRL (0x25)
-#define CyRTPRH (0x24)
-#define CyCOR1 (0x10)
-#define CyPARITY_NONE (0x00)
-#define CyPARITY_E (0x40)
-#define CyPARITY_O (0xC0)
-#define Cy_5_BITS (0x04)
-#define Cy_6_BITS (0x05)
-#define Cy_7_BITS (0x06)
-#define Cy_8_BITS (0x07)
-#define CyCOR2 (0x17)
-#define CyETC (0x20)
-#define CyCtsAE (0x02)
-#define CyCOR3 (0x16)
-#define Cy_1_STOP (0x02)
-#define Cy_2_STOP (0x04)
-#define CyCOR4 (0x15)
-#define CyREC_FIFO (0x0F) /* Receive FIFO threshold */
-#define CyCOR5 (0x14)
-#define CyCOR6 (0x18)
-#define CyCOR7 (0x07)
-#define CyRBPR (0xcb)
-#define CyRCOR (0xc8)
-#define CyTBPR (0xc3)
-#define CyTCOR (0xc0)
-#define CySCHR1 (0x1f)
-#define CySCHR2 (0x1e)
-#define CyTPR (0xda)
-#define CyPILR1 (0xe3)
-#define CyPILR2 (0xe0)
-#define CyPILR3 (0xe1)
-#define CyCMR (0x1b)
-#define CyASYNC (0x02)
-#define CyLICR (0x26)
-#define CyLIVR (0x09)
-#define CySCRL (0x23)
-#define CySCRH (0x22)
-#define CyTFTC (0x80)
-
-
-/* max number of chars in the FIFO */
-
-#define CyMAX_CHAR_FIFO 12
-
-/***************************************************************************/
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index a416e92012ef..f41dcc949218 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -69,7 +69,6 @@ struct uart_port;
struct uart_8250_port;
int serial8250_register_8250_port(struct uart_8250_port *);
-int serial8250_register_port(struct uart_port *);
void serial8250_unregister_port(int line);
void serial8250_suspend_port(int line);
void serial8250_resume_port(int line);
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 65db9928e15f..0253c2022e53 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -47,7 +47,8 @@
#define PORT_U6_16550A 19 /* ST-Ericsson U6xxx internal UART */
#define PORT_TEGRA 20 /* NVIDIA Tegra internal UART */
#define PORT_XR17D15X 21 /* Exar XR17D15x UART */
-#define PORT_MAX_8250 21 /* max port ID */
+#define PORT_LPC3220 22 /* NXP LPC32xx SoC "Standard" UART */
+#define PORT_MAX_8250 22 /* max port ID */
/*
* ARM specific type numbers. These are not currently guaranteed
diff --git a/include/linux/stallion.h b/include/linux/stallion.h
deleted file mode 100644
index 336af33c6ea4..000000000000
--- a/include/linux/stallion.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*****************************************************************************/
-
-/*
- * stallion.h -- stallion multiport serial driver.
- *
- * Copyright (C) 1996-1998 Stallion Technologies
- * Copyright (C) 1994-1996 Greg Ungerer.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*****************************************************************************/
-#ifndef _STALLION_H
-#define _STALLION_H
-/*****************************************************************************/
-
-/*
- * Define important driver constants here.
- */
-#define STL_MAXBRDS 4
-#define STL_MAXPANELS 4
-#define STL_MAXBANKS 8
-#define STL_PORTSPERPANEL 16
-#define STL_MAXPORTS 64
-#define STL_MAXDEVS (STL_MAXBRDS * STL_MAXPORTS)
-
-
-/*
- * Define a set of structures to hold all the board/panel/port info
- * for our ports. These will be dynamically allocated as required.
- */
-
-/*
- * Define a ring queue structure for each port. This will hold the
- * TX data waiting to be output. Characters are fed into this buffer
- * from the line discipline (or even direct from user space!) and
- * then fed into the UARTs during interrupts. Will use a classic ring
- * queue here for this. The good thing about this type of ring queue
- * is that the head and tail pointers can be updated without interrupt
- * protection - since "write" code only needs to change the head, and
- * interrupt code only needs to change the tail.
- */
-struct stlrq {
- char *buf;
- char *head;
- char *tail;
-};
-
-/*
- * Port, panel and board structures to hold status info about each.
- * The board structure contains pointers to structures for each panel
- * connected to it, and in turn each panel structure contains pointers
- * for each port structure for each port on that panel. Note that
- * the port structure also contains the board and panel number that it
- * is associated with, this makes it (fairly) easy to get back to the
- * board/panel info for a port.
- */
-struct stlport {
- unsigned long magic;
- struct tty_port port;
- unsigned int portnr;
- unsigned int panelnr;
- unsigned int brdnr;
- int ioaddr;
- int uartaddr;
- unsigned int pagenr;
- unsigned long istate;
- int baud_base;
- int custom_divisor;
- int close_delay;
- int closing_wait;
- int openwaitcnt;
- int brklen;
- unsigned int sigs;
- unsigned int rxignoremsk;
- unsigned int rxmarkmsk;
- unsigned int imr;
- unsigned int crenable;
- unsigned long clk;
- unsigned long hwid;
- void *uartp;
- comstats_t stats;
- struct stlrq tx;
-};
-
-struct stlpanel {
- unsigned long magic;
- unsigned int panelnr;
- unsigned int brdnr;
- unsigned int pagenr;
- unsigned int nrports;
- int iobase;
- void *uartp;
- void (*isr)(struct stlpanel *panelp, unsigned int iobase);
- unsigned int hwid;
- unsigned int ackmask;
- struct stlport *ports[STL_PORTSPERPANEL];
-};
-
-struct stlbrd {
- unsigned long magic;
- unsigned int brdnr;
- unsigned int brdtype;
- unsigned int state;
- unsigned int nrpanels;
- unsigned int nrports;
- unsigned int nrbnks;
- int irq;
- int irqtype;
- int (*isr)(struct stlbrd *brdp);
- unsigned int ioaddr1;
- unsigned int ioaddr2;
- unsigned int iosize1;
- unsigned int iosize2;
- unsigned int iostatus;
- unsigned int ioctrl;
- unsigned int ioctrlval;
- unsigned int hwid;
- unsigned long clk;
- unsigned int bnkpageaddr[STL_MAXBANKS];
- unsigned int bnkstataddr[STL_MAXBANKS];
- struct stlpanel *bnk2panel[STL_MAXBANKS];
- struct stlpanel *panels[STL_MAXPANELS];
-};
-
-
-/*
- * Define MAGIC numbers used for above structures.
- */
-#define STL_PORTMAGIC 0x5a7182c9
-#define STL_PANELMAGIC 0x7ef621a1
-#define STL_BOARDMAGIC 0xa2267f52
-
-/*****************************************************************************/
-#endif
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 9f47ab540f65..7f9d7df9b131 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -268,6 +268,7 @@ struct tty_struct {
struct mutex ldisc_mutex;
struct tty_ldisc *ldisc;
+ struct mutex legacy_mutex;
struct mutex termios_mutex;
spinlock_t ctrl_lock;
/* Termios values are protected by the termios mutex */
@@ -497,6 +498,9 @@ extern int tty_write_lock(struct tty_struct *tty, int ndelay);
#define tty_is_writelocked(tty) (mutex_is_locked(&tty->atomic_write_lock))
extern void tty_port_init(struct tty_port *port);
+extern struct device *tty_port_register_device(struct tty_port *port,
+ struct tty_driver *driver, unsigned index,
+ struct device *device);
extern int tty_port_alloc_xmit_buf(struct tty_port *port);
extern void tty_port_free_xmit_buf(struct tty_port *port);
extern void tty_port_put(struct tty_port *port);
@@ -521,6 +525,8 @@ extern int tty_port_close_start(struct tty_port *port,
extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
extern void tty_port_close(struct tty_port *port,
struct tty_struct *tty, struct file *filp);
+extern int tty_port_install(struct tty_port *port, struct tty_driver *driver,
+ struct tty_struct *tty);
extern int tty_port_open(struct tty_port *port,
struct tty_struct *tty, struct file *filp);
static inline int tty_port_users(struct tty_port *port)
@@ -605,8 +611,12 @@ extern long vt_compat_ioctl(struct tty_struct *tty,
/* tty_mutex.c */
/* functions for preparation of BKL removal */
-extern void __lockfunc tty_lock(void) __acquires(tty_lock);
-extern void __lockfunc tty_unlock(void) __releases(tty_lock);
+extern void __lockfunc tty_lock(struct tty_struct *tty);
+extern void __lockfunc tty_unlock(struct tty_struct *tty);
+extern void __lockfunc tty_lock_pair(struct tty_struct *tty,
+ struct tty_struct *tty2);
+extern void __lockfunc tty_unlock_pair(struct tty_struct *tty,
+ struct tty_struct *tty2);
/*
* this shall be called only from where BTM is held (like close)
@@ -621,9 +631,9 @@ extern void __lockfunc tty_unlock(void) __releases(tty_lock);
static inline void tty_wait_until_sent_from_close(struct tty_struct *tty,
long timeout)
{
- tty_unlock(); /* tty->ops->close holds the BTM, drop it while waiting */
+ tty_unlock(tty); /* tty->ops->close holds the BTM, drop it while waiting */
tty_wait_until_sent(tty, timeout);
- tty_lock();
+ tty_lock(tty);
}
/*
@@ -638,16 +648,16 @@ static inline void tty_wait_until_sent_from_close(struct tty_struct *tty,
*
* Do not use in new code.
*/
-#define wait_event_interruptible_tty(wq, condition) \
+#define wait_event_interruptible_tty(tty, wq, condition) \
({ \
int __ret = 0; \
if (!(condition)) { \
- __wait_event_interruptible_tty(wq, condition, __ret); \
+ __wait_event_interruptible_tty(tty, wq, condition, __ret); \
} \
__ret; \
})
-#define __wait_event_interruptible_tty(wq, condition, ret) \
+#define __wait_event_interruptible_tty(tty, wq, condition, ret) \
do { \
DEFINE_WAIT(__wait); \
\
@@ -656,9 +666,9 @@ do { \
if (condition) \
break; \
if (!signal_pending(current)) { \
- tty_unlock(); \
+ tty_unlock(tty); \
schedule(); \
- tty_lock(); \
+ tty_lock(tty); \
continue; \
} \
ret = -ERESTARTSYS; \
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 6e6dbb7447b6..04419c141b00 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -313,6 +313,7 @@ struct tty_driver {
* Pointer to the tty data structures
*/
struct tty_struct **ttys;
+ struct tty_port **ports;
struct ktermios **termios;
void *driver_state;
diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h
index 59ba38bc400f..80ffde3bb164 100644
--- a/include/net/irda/ircomm_tty.h
+++ b/include/net/irda/ircomm_tty.h
@@ -52,21 +52,16 @@
/* Same for payload size. See qos.c for the smallest max data size */
#define IRCOMM_TTY_DATA_UNINITIALISED (64 - IRCOMM_TTY_HDR_UNINITIALISED)
-/* Those are really defined in include/linux/serial.h - Jean II */
-#define ASYNC_B_INITIALIZED 31 /* Serial port was initialized */
-#define ASYNC_B_NORMAL_ACTIVE 29 /* Normal device is active */
-#define ASYNC_B_CLOSING 27 /* Serial port is closing */
-
/*
* IrCOMM TTY driver state
*/
struct ircomm_tty_cb {
irda_queue_t queue; /* Must be first */
+ struct tty_port port;
magic_t magic;
int state; /* Connect state */
- struct tty_struct *tty;
struct ircomm_cb *ircomm; /* IrCOMM layer instance */
struct sk_buff *tx_skb; /* Transmit buffer */
@@ -80,7 +75,6 @@ struct ircomm_tty_cb {
LOCAL_FLOW flow; /* IrTTP flow status */
int line;
- unsigned long flags;
__u8 dlsap_sel;
__u8 slsap_sel;
@@ -97,19 +91,10 @@ struct ircomm_tty_cb {
void *skey;
void *ckey;
- wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
struct timer_list watchdog_timer;
struct work_struct tqueue;
- unsigned short close_delay;
- unsigned short closing_wait; /* time to wait before closing */
-
- int open_count;
- int blocked_open; /* # of blocked opens */
-
/* Protect concurent access to :
- * o self->open_count
* o self->ctrl_skb
* o self->tx_skb
* Maybe other things may gain to be protected as well...
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index d1820ff14aee..aa5d73b786ac 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -710,9 +710,9 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
break;
}
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&dev->wait, &wait);
diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c
index 8b915f3ac3b9..308939128359 100644
--- a/net/irda/ircomm/ircomm_param.c
+++ b/net/irda/ircomm/ircomm_param.c
@@ -99,7 +99,6 @@ pi_param_info_t ircomm_param_info = { pi_major_call_table, 3, 0x0f, 4 };
*/
int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
{
- struct tty_struct *tty;
unsigned long flags;
struct sk_buff *skb;
int count;
@@ -109,10 +108,6 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
IRDA_ASSERT(self != NULL, return -1;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
- tty = self->tty;
- if (!tty)
- return 0;
-
/* Make sure we don't send parameters for raw mode */
if (self->service_type == IRCOMM_3_WIRE_RAW)
return 0;
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 6b9d5a0e42f9..4e35b45c1c73 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -104,6 +104,35 @@ static const struct tty_operations ops = {
#endif /* CONFIG_PROC_FS */
};
+static void ircomm_port_raise_dtr_rts(struct tty_port *port, int raise)
+{
+ struct ircomm_tty_cb *self = container_of(port, struct ircomm_tty_cb,
+ port);
+ /*
+ * Here, we use to lock those two guys, but as ircomm_param_request()
+ * does it itself, I don't see the point (and I see the deadlock).
+ * Jean II
+ */
+ if (raise)
+ self->settings.dte |= IRCOMM_RTS | IRCOMM_DTR;
+ else
+ self->settings.dte &= ~(IRCOMM_RTS | IRCOMM_DTR);
+
+ ircomm_param_request(self, IRCOMM_DTE, TRUE);
+}
+
+static int ircomm_port_carrier_raised(struct tty_port *port)
+{
+ struct ircomm_tty_cb *self = container_of(port, struct ircomm_tty_cb,
+ port);
+ return self->settings.dce & IRCOMM_CD;
+}
+
+static const struct tty_port_operations ircomm_port_ops = {
+ .dtr_rts = ircomm_port_raise_dtr_rts,
+ .carrier_raised = ircomm_port_carrier_raised,
+};
+
/*
* Function ircomm_tty_init()
*
@@ -194,7 +223,7 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self)
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
/* Check if already open */
- if (test_and_set_bit(ASYNC_B_INITIALIZED, &self->flags)) {
+ if (test_and_set_bit(ASYNCB_INITIALIZED, &self->port.flags)) {
IRDA_DEBUG(2, "%s(), already open so break out!\n", __func__ );
return 0;
}
@@ -231,7 +260,7 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self)
return 0;
err:
- clear_bit(ASYNC_B_INITIALIZED, &self->flags);
+ clear_bit(ASYNCB_INITIALIZED, &self->port.flags);
return ret;
}
@@ -242,25 +271,23 @@ err:
*
*/
static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
- struct file *filp)
+ struct tty_struct *tty, struct file *filp)
{
+ struct tty_port *port = &self->port;
DECLARE_WAITQUEUE(wait, current);
int retval;
int do_clocal = 0, extra_count = 0;
unsigned long flags;
- struct tty_struct *tty;
IRDA_DEBUG(2, "%s()\n", __func__ );
- tty = self->tty;
-
/*
* If non-blocking mode is set, or the port is not enabled,
* then make the check up front and then exit.
*/
if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
/* nonblock mode is set or port is not enabled */
- self->flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __func__ );
return 0;
}
@@ -272,42 +299,34 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
/* Wait for carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in
- * this loop, self->open_count is dropped by one, so that
+ * this loop, port->count is dropped by one, so that
* mgsl_close() knows when to free things. We restore it upon
* exit, either normal or abnormal.
*/
retval = 0;
- add_wait_queue(&self->open_wait, &wait);
+ add_wait_queue(&port->open_wait, &wait);
IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n",
- __FILE__,__LINE__, tty->driver->name, self->open_count );
+ __FILE__, __LINE__, tty->driver->name, port->count);
- /* As far as I can see, we protect open_count - Jean II */
- spin_lock_irqsave(&self->spinlock, flags);
+ spin_lock_irqsave(&port->lock, flags);
if (!tty_hung_up_p(filp)) {
extra_count = 1;
- self->open_count--;
+ port->count--;
}
- spin_unlock_irqrestore(&self->spinlock, flags);
- self->blocked_open++;
+ spin_unlock_irqrestore(&port->lock, flags);
+ port->blocked_open++;
while (1) {
- if (tty->termios->c_cflag & CBAUD) {
- /* Here, we use to lock those two guys, but
- * as ircomm_param_request() does it itself,
- * I don't see the point (and I see the deadlock).
- * Jean II */
- self->settings.dte |= IRCOMM_RTS + IRCOMM_DTR;
-
- ircomm_param_request(self, IRCOMM_DTE, TRUE);
- }
+ if (tty->termios->c_cflag & CBAUD)
+ tty_port_raise_dtr_rts(port);
current->state = TASK_INTERRUPTIBLE;
if (tty_hung_up_p(filp) ||
- !test_bit(ASYNC_B_INITIALIZED, &self->flags)) {
- retval = (self->flags & ASYNC_HUP_NOTIFY) ?
+ !test_bit(ASYNCB_INITIALIZED, &port->flags)) {
+ retval = (port->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS;
break;
}
@@ -317,8 +336,8 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
* specified, we cannot return before the IrCOMM link is
* ready
*/
- if (!test_bit(ASYNC_B_CLOSING, &self->flags) &&
- (do_clocal || (self->settings.dce & IRCOMM_CD)) &&
+ if (!test_bit(ASYNCB_CLOSING, &port->flags) &&
+ (do_clocal || tty_port_carrier_raised(port)) &&
self->state == IRCOMM_TTY_READY)
{
break;
@@ -330,27 +349,27 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
}
IRDA_DEBUG(1, "%s(%d):block_til_ready blocking on %s open_count=%d\n",
- __FILE__,__LINE__, tty->driver->name, self->open_count );
+ __FILE__, __LINE__, tty->driver->name, port->count);
schedule();
}
__set_current_state(TASK_RUNNING);
- remove_wait_queue(&self->open_wait, &wait);
+ remove_wait_queue(&port->open_wait, &wait);
if (extra_count) {
/* ++ is not atomic, so this should be protected - Jean II */
- spin_lock_irqsave(&self->spinlock, flags);
- self->open_count++;
- spin_unlock_irqrestore(&self->spinlock, flags);
+ spin_lock_irqsave(&port->lock, flags);
+ port->count++;
+ spin_unlock_irqrestore(&port->lock, flags);
}
- self->blocked_open--;
+ port->blocked_open--;
IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n",
- __FILE__,__LINE__, tty->driver->name, self->open_count);
+ __FILE__, __LINE__, tty->driver->name, port->count);
if (!retval)
- self->flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
return retval;
}
@@ -381,6 +400,8 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
return -ENOMEM;
}
+ tty_port_init(&self->port);
+ self->port.ops = &ircomm_port_ops;
self->magic = IRCOMM_TTY_MAGIC;
self->flow = FLOW_STOP;
@@ -388,13 +409,9 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
INIT_WORK(&self->tqueue, ircomm_tty_do_softint);
self->max_header_size = IRCOMM_TTY_HDR_UNINITIALISED;
self->max_data_size = IRCOMM_TTY_DATA_UNINITIALISED;
- self->close_delay = 5*HZ/10;
- self->closing_wait = 30*HZ;
/* Init some important stuff */
init_timer(&self->watchdog_timer);
- init_waitqueue_head(&self->open_wait);
- init_waitqueue_head(&self->close_wait);
spin_lock_init(&self->spinlock);
/*
@@ -408,27 +425,28 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
tty->termios->c_oflag = 0;
/* Insert into hash */
+ /* FIXME there is a window from find to here */
hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL);
}
/* ++ is not atomic, so this should be protected - Jean II */
- spin_lock_irqsave(&self->spinlock, flags);
- self->open_count++;
+ spin_lock_irqsave(&self->port.lock, flags);
+ self->port.count++;
tty->driver_data = self;
- self->tty = tty;
- spin_unlock_irqrestore(&self->spinlock, flags);
+ spin_unlock_irqrestore(&self->port.lock, flags);
+ tty_port_tty_set(&self->port, tty);
IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __func__ , tty->driver->name,
- self->line, self->open_count);
+ self->line, self->port.count);
/* Not really used by us, but lets do it anyway */
- self->tty->low_latency = (self->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ tty->low_latency = (self->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
/*
* If the port is the middle of closing, bail out now
*/
if (tty_hung_up_p(filp) ||
- test_bit(ASYNC_B_CLOSING, &self->flags)) {
+ test_bit(ASYNCB_CLOSING, &self->port.flags)) {
/* Hm, why are we blocking on ASYNC_CLOSING if we
* do return -EAGAIN/-ERESTARTSYS below anyway?
@@ -438,14 +456,15 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
* probably better sleep uninterruptible?
*/
- if (wait_event_interruptible(self->close_wait, !test_bit(ASYNC_B_CLOSING, &self->flags))) {
+ if (wait_event_interruptible(self->port.close_wait,
+ !test_bit(ASYNCB_CLOSING, &self->port.flags))) {
IRDA_WARNING("%s - got signal while blocking on ASYNC_CLOSING!\n",
__func__);
return -ERESTARTSYS;
}
#ifdef SERIAL_DO_RESTART
- return (self->flags & ASYNC_HUP_NOTIFY) ?
+ return (self->port.flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS;
#else
return -EAGAIN;
@@ -469,7 +488,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
if (ret)
return ret;
- ret = ircomm_tty_block_til_ready(self, filp);
+ ret = ircomm_tty_block_til_ready(self, tty, filp);
if (ret) {
IRDA_DEBUG(2,
"%s(), returning after block_til_ready with %d\n", __func__ ,
@@ -489,81 +508,22 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
- unsigned long flags;
+ struct tty_port *port = &self->port;
IRDA_DEBUG(0, "%s()\n", __func__ );
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
- spin_lock_irqsave(&self->spinlock, flags);
-
- if (tty_hung_up_p(filp)) {
- spin_unlock_irqrestore(&self->spinlock, flags);
-
- IRDA_DEBUG(0, "%s(), returning 1\n", __func__ );
- return;
- }
-
- if ((tty->count == 1) && (self->open_count != 1)) {
- /*
- * Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. state->count should always
- * be one in these conditions. If it's greater than
- * one, we've got real problems, since it means the
- * serial port won't be shutdown.
- */
- IRDA_DEBUG(0, "%s(), bad serial port count; "
- "tty->count is 1, state->count is %d\n", __func__ ,
- self->open_count);
- self->open_count = 1;
- }
-
- if (--self->open_count < 0) {
- IRDA_ERROR("%s(), bad serial port count for ttys%d: %d\n",
- __func__, self->line, self->open_count);
- self->open_count = 0;
- }
- if (self->open_count) {
- spin_unlock_irqrestore(&self->spinlock, flags);
-
- IRDA_DEBUG(0, "%s(), open count > 0\n", __func__ );
+ if (tty_port_close_start(port, tty, filp) == 0)
return;
- }
-
- /* Hum... Should be test_and_set_bit ??? - Jean II */
- set_bit(ASYNC_B_CLOSING, &self->flags);
-
- /* We need to unlock here (we were unlocking at the end of this
- * function), because tty_wait_until_sent() may schedule.
- * I don't know if the rest should be protected somehow,
- * so someone should check. - Jean II */
- spin_unlock_irqrestore(&self->spinlock, flags);
-
- /*
- * Now we wait for the transmit buffer to clear; and we notify
- * the line discipline to only process XON/XOFF characters.
- */
- tty->closing = 1;
- if (self->closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent_from_close(tty, self->closing_wait);
ircomm_tty_shutdown(self);
tty_driver_flush_buffer(tty);
- tty_ldisc_flush(tty);
- tty->closing = 0;
- self->tty = NULL;
-
- if (self->blocked_open) {
- if (self->close_delay)
- schedule_timeout_interruptible(self->close_delay);
- wake_up_interruptible(&self->open_wait);
- }
-
- self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- wake_up_interruptible(&self->close_wait);
+ tty_port_close_end(port, tty);
+ tty_port_tty_set(port, NULL);
}
/*
@@ -606,7 +566,7 @@ static void ircomm_tty_do_softint(struct work_struct *work)
if (!self || self->magic != IRCOMM_TTY_MAGIC)
return;
- tty = self->tty;
+ tty = tty_port_tty_get(&self->port);
if (!tty)
return;
@@ -627,7 +587,7 @@ static void ircomm_tty_do_softint(struct work_struct *work)
}
if (tty->hw_stopped)
- return;
+ goto put;
/* Unlink transmit buffer */
spin_lock_irqsave(&self->spinlock, flags);
@@ -646,6 +606,8 @@ static void ircomm_tty_do_softint(struct work_struct *work)
/* Check if user (still) wants to be waken up */
tty_wakeup(tty);
+put:
+ tty_kref_put(tty);
}
/*
@@ -955,7 +917,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
IRDA_DEBUG(0, "%s()\n", __func__ );
- if (!test_and_clear_bit(ASYNC_B_INITIALIZED, &self->flags))
+ if (!test_and_clear_bit(ASYNCB_INITIALIZED, &self->port.flags))
return;
ircomm_tty_detach_cable(self);
@@ -994,6 +956,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
static void ircomm_tty_hangup(struct tty_struct *tty)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ struct tty_port *port = &self->port;
unsigned long flags;
IRDA_DEBUG(0, "%s()\n", __func__ );
@@ -1004,14 +967,17 @@ static void ircomm_tty_hangup(struct tty_struct *tty)
/* ircomm_tty_flush_buffer(tty); */
ircomm_tty_shutdown(self);
- /* I guess we need to lock here - Jean II */
- spin_lock_irqsave(&self->spinlock, flags);
- self->flags &= ~ASYNC_NORMAL_ACTIVE;
- self->tty = NULL;
- self->open_count = 0;
- spin_unlock_irqrestore(&self->spinlock, flags);
+ spin_lock_irqsave(&port->lock, flags);
+ port->flags &= ~ASYNC_NORMAL_ACTIVE;
+ if (port->tty) {
+ set_bit(TTY_IO_ERROR, &port->tty->flags);
+ tty_kref_put(port->tty);
+ }
+ port->tty = NULL;
+ port->count = 0;
+ spin_unlock_irqrestore(&port->lock, flags);
- wake_up_interruptible(&self->open_wait);
+ wake_up_interruptible(&port->open_wait);
}
/*
@@ -1071,20 +1037,20 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
- tty = self->tty;
+ tty = tty_port_tty_get(&self->port);
status = self->settings.dce;
if (status & IRCOMM_DCE_DELTA_ANY) {
/*wake_up_interruptible(&self->delta_msr_wait);*/
}
- if ((self->flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) {
+ if ((self->port.flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) {
IRDA_DEBUG(2,
"%s(), ircomm%d CD now %s...\n", __func__ , self->line,
(status & IRCOMM_CD) ? "on" : "off");
if (status & IRCOMM_CD) {
- wake_up_interruptible(&self->open_wait);
+ wake_up_interruptible(&self->port.open_wait);
} else {
IRDA_DEBUG(2,
"%s(), Doing serial hangup..\n", __func__ );
@@ -1092,10 +1058,10 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
tty_hangup(tty);
/* Hangup will remote the tty, so better break out */
- return;
+ goto put;
}
}
- if (self->flags & ASYNC_CTS_FLOW) {
+ if (tty && self->port.flags & ASYNC_CTS_FLOW) {
if (tty->hw_stopped) {
if (status & IRCOMM_CTS) {
IRDA_DEBUG(2,
@@ -1103,10 +1069,10 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
tty->hw_stopped = 0;
/* Wake up processes blocked on open */
- wake_up_interruptible(&self->open_wait);
+ wake_up_interruptible(&self->port.open_wait);
schedule_work(&self->tqueue);
- return;
+ goto put;
}
} else {
if (!(status & IRCOMM_CTS)) {
@@ -1116,6 +1082,8 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
}
}
}
+put:
+ tty_kref_put(tty);
}
/*
@@ -1128,6 +1096,7 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
struct sk_buff *skb)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+ struct tty_struct *tty;
IRDA_DEBUG(2, "%s()\n", __func__ );
@@ -1135,7 +1104,8 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
IRDA_ASSERT(skb != NULL, return -1;);
- if (!self->tty) {
+ tty = tty_port_tty_get(&self->port);
+ if (!tty) {
IRDA_DEBUG(0, "%s(), no tty!\n", __func__ );
return 0;
}
@@ -1146,7 +1116,7 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
* Devices like WinCE can do this, and since they don't send any
* params, we can just as well declare the hardware for running.
*/
- if (self->tty->hw_stopped && (self->flow == FLOW_START)) {
+ if (tty->hw_stopped && (self->flow == FLOW_START)) {
IRDA_DEBUG(0, "%s(), polling for line settings!\n", __func__ );
ircomm_param_request(self, IRCOMM_POLL, TRUE);
@@ -1159,8 +1129,9 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
* Use flip buffer functions since the code may be called from interrupt
* context
*/
- tty_insert_flip_string(self->tty, skb->data, skb->len);
- tty_flip_buffer_push(self->tty);
+ tty_insert_flip_string(tty, skb->data, skb->len);
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
/* No need to kfree_skb - see ircomm_ttp_data_indication() */
@@ -1211,12 +1182,13 @@ static void ircomm_tty_flow_indication(void *instance, void *sap,
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
- tty = self->tty;
+ tty = tty_port_tty_get(&self->port);
switch (cmd) {
case FLOW_START:
IRDA_DEBUG(2, "%s(), hw start!\n", __func__ );
- tty->hw_stopped = 0;
+ if (tty)
+ tty->hw_stopped = 0;
/* ircomm_tty_do_softint will take care of the rest */
schedule_work(&self->tqueue);
@@ -1224,15 +1196,19 @@ static void ircomm_tty_flow_indication(void *instance, void *sap,
default: /* If we get here, something is very wrong, better stop */
case FLOW_STOP:
IRDA_DEBUG(2, "%s(), hw stopped!\n", __func__ );
- tty->hw_stopped = 1;
+ if (tty)
+ tty->hw_stopped = 1;
break;
}
+
+ tty_kref_put(tty);
self->flow = cmd;
}
#ifdef CONFIG_PROC_FS
static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m)
{
+ struct tty_struct *tty;
char sep;
seq_printf(m, "State: %s\n", ircomm_tty_state[self->state]);
@@ -1328,40 +1304,43 @@ static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m)
seq_puts(m, "Flags:");
sep = ' ';
- if (self->flags & ASYNC_CTS_FLOW) {
+ if (self->port.flags & ASYNC_CTS_FLOW) {
seq_printf(m, "%cASYNC_CTS_FLOW", sep);
sep = '|';
}
- if (self->flags & ASYNC_CHECK_CD) {
+ if (self->port.flags & ASYNC_CHECK_CD) {
seq_printf(m, "%cASYNC_CHECK_CD", sep);
sep = '|';
}
- if (self->flags & ASYNC_INITIALIZED) {
+ if (self->port.flags & ASYNC_INITIALIZED) {
seq_printf(m, "%cASYNC_INITIALIZED", sep);
sep = '|';
}
- if (self->flags & ASYNC_LOW_LATENCY) {
+ if (self->port.flags & ASYNC_LOW_LATENCY) {
seq_printf(m, "%cASYNC_LOW_LATENCY", sep);
sep = '|';
}
- if (self->flags & ASYNC_CLOSING) {
+ if (self->port.flags & ASYNC_CLOSING) {
seq_printf(m, "%cASYNC_CLOSING", sep);
sep = '|';
}
- if (self->flags & ASYNC_NORMAL_ACTIVE) {
+ if (self->port.flags & ASYNC_NORMAL_ACTIVE) {
seq_printf(m, "%cASYNC_NORMAL_ACTIVE", sep);
sep = '|';
}
seq_putc(m, '\n');
seq_printf(m, "Role: %s\n", self->client ? "client" : "server");
- seq_printf(m, "Open count: %d\n", self->open_count);
+ seq_printf(m, "Open count: %d\n", self->port.count);
seq_printf(m, "Max data size: %d\n", self->max_data_size);
seq_printf(m, "Max header size: %d\n", self->max_header_size);
- if (self->tty)
+ tty = tty_port_tty_get(&self->port);
+ if (tty) {
seq_printf(m, "Hardware: %s\n",
- self->tty->hw_stopped ? "Stopped" : "Running");
+ tty->hw_stopped ? "Stopped" : "Running");
+ tty_kref_put(tty);
+ }
}
static int ircomm_tty_proc_show(struct seq_file *m, void *v)
diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
index b65d66e0d817..3ab70e7a0715 100644
--- a/net/irda/ircomm/ircomm_tty_attach.c
+++ b/net/irda/ircomm/ircomm_tty_attach.c
@@ -130,6 +130,8 @@ static int (*state[])(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
*/
int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)
{
+ struct tty_struct *tty;
+
IRDA_DEBUG(0, "%s()\n", __func__ );
IRDA_ASSERT(self != NULL, return -1;);
@@ -142,7 +144,11 @@ int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)
}
/* Make sure nobody tries to write before the link is up */
- self->tty->hw_stopped = 1;
+ tty = tty_port_tty_get(&self->port);
+ if (tty) {
+ tty->hw_stopped = 1;
+ tty_kref_put(tty);
+ }
ircomm_tty_ias_register(self);
@@ -398,23 +404,26 @@ void ircomm_tty_disconnect_indication(void *instance, void *sap,
struct sk_buff *skb)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+ struct tty_struct *tty;
IRDA_DEBUG(2, "%s()\n", __func__ );
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
- if (!self->tty)
+ tty = tty_port_tty_get(&self->port);
+ if (!tty)
return;
/* This will stop control data transfers */
self->flow = FLOW_STOP;
/* Stop data transfers */
- self->tty->hw_stopped = 1;
+ tty->hw_stopped = 1;
ircomm_tty_do_event(self, IRCOMM_TTY_DISCONNECT_INDICATION, NULL,
NULL);
+ tty_kref_put(tty);
}
/*
@@ -550,12 +559,15 @@ void ircomm_tty_connect_indication(void *instance, void *sap,
*/
void ircomm_tty_link_established(struct ircomm_tty_cb *self)
{
+ struct tty_struct *tty;
+
IRDA_DEBUG(2, "%s()\n", __func__ );
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
- if (!self->tty)
+ tty = tty_port_tty_get(&self->port);
+ if (!tty)
return;
del_timer(&self->watchdog_timer);
@@ -566,19 +578,22 @@ void ircomm_tty_link_established(struct ircomm_tty_cb *self)
* will have to wait for the peer device (DCE) to raise the CTS
* line.
*/
- if ((self->flags & ASYNC_CTS_FLOW) && ((self->settings.dce & IRCOMM_CTS) == 0)) {
+ if ((self->port.flags & ASYNC_CTS_FLOW) &&
+ ((self->settings.dce & IRCOMM_CTS) == 0)) {
IRDA_DEBUG(0, "%s(), waiting for CTS ...\n", __func__ );
- return;
+ goto put;
} else {
IRDA_DEBUG(1, "%s(), starting hardware!\n", __func__ );
- self->tty->hw_stopped = 0;
+ tty->hw_stopped = 0;
/* Wake up processes blocked on open */
- wake_up_interruptible(&self->open_wait);
+ wake_up_interruptible(&self->port.open_wait);
}
schedule_work(&self->tqueue);
+put:
+ tty_kref_put(tty);
}
/*
@@ -977,14 +992,17 @@ static int ircomm_tty_state_ready(struct ircomm_tty_cb *self,
ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
ircomm_tty_start_watchdog_timer(self, 3*HZ);
- if (self->flags & ASYNC_CHECK_CD) {
+ if (self->port.flags & ASYNC_CHECK_CD) {
/* Drop carrier */
self->settings.dce = IRCOMM_DELTA_CD;
ircomm_tty_check_modem_status(self);
} else {
+ struct tty_struct *tty = tty_port_tty_get(&self->port);
IRDA_DEBUG(0, "%s(), hanging up!\n", __func__ );
- if (self->tty)
- tty_hangup(self->tty);
+ if (tty) {
+ tty_hangup(tty);
+ tty_kref_put(tty);
+ }
}
break;
default:
diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c
index d0667d68351d..0eab6500e99f 100644
--- a/net/irda/ircomm/ircomm_tty_ioctl.c
+++ b/net/irda/ircomm/ircomm_tty_ioctl.c
@@ -52,17 +52,18 @@
* Change speed of the driver. If the remote device is a DCE, then this
* should make it change the speed of its serial port
*/
-static void ircomm_tty_change_speed(struct ircomm_tty_cb *self)
+static void ircomm_tty_change_speed(struct ircomm_tty_cb *self,
+ struct tty_struct *tty)
{
unsigned int cflag, cval;
int baud;
IRDA_DEBUG(2, "%s()\n", __func__ );
- if (!self->tty || !self->tty->termios || !self->ircomm)
+ if (!self->ircomm)
return;
- cflag = self->tty->termios->c_cflag;
+ cflag = tty->termios->c_cflag;
/* byte size and parity */
switch (cflag & CSIZE) {
@@ -81,7 +82,7 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self)
cval |= IRCOMM_PARITY_EVEN;
/* Determine divisor based on baud rate */
- baud = tty_get_baud_rate(self->tty);
+ baud = tty_get_baud_rate(tty);
if (!baud)
baud = 9600; /* B0 transition handled in rs_set_termios */
@@ -90,19 +91,19 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self)
/* CTS flow control flag and modem status interrupts */
if (cflag & CRTSCTS) {
- self->flags |= ASYNC_CTS_FLOW;
+ self->port.flags |= ASYNC_CTS_FLOW;
self->settings.flow_control |= IRCOMM_RTS_CTS_IN;
/* This got me. Bummer. Jean II */
if (self->service_type == IRCOMM_3_WIRE_RAW)
IRDA_WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __func__);
} else {
- self->flags &= ~ASYNC_CTS_FLOW;
+ self->port.flags &= ~ASYNC_CTS_FLOW;
self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN;
}
if (cflag & CLOCAL)
- self->flags &= ~ASYNC_CHECK_CD;
+ self->port.flags &= ~ASYNC_CHECK_CD;
else
- self->flags |= ASYNC_CHECK_CD;
+ self->port.flags |= ASYNC_CHECK_CD;
#if 0
/*
* Set up parity check flag
@@ -159,7 +160,7 @@ void ircomm_tty_set_termios(struct tty_struct *tty,
return;
}
- ircomm_tty_change_speed(self);
+ ircomm_tty_change_speed(self, tty);
/* Handle transition to B0 status */
if ((old_termios->c_cflag & CBAUD) &&
@@ -270,10 +271,10 @@ static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self,
memset(&info, 0, sizeof(info));
info.line = self->line;
- info.flags = self->flags;
+ info.flags = self->port.flags;
info.baud_base = self->settings.data_rate;
- info.close_delay = self->close_delay;
- info.closing_wait = self->closing_wait;
+ info.close_delay = self->port.close_delay;
+ info.closing_wait = self->port.closing_wait;
/* For compatibility */
info.type = PORT_16550A;