Merge branch 'v3.6-rc7' into tty-next

This is to sync up on Linus's branch to get the other tty and core changes.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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 0000000..0d439df
--- /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 b8b27b0..0847fde 100644
--- a/Documentation/devicetree/bindings/tty/serial/of-serial.txt
+++ b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
@@ -9,6 +9,7 @@
 	- "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 45e248c..87eebfe 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -150,9 +150,11 @@
 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 acfd0e0..fb6e4ea 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -19,9 +19,11 @@
 {
 	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 @@
 {
 	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 @@
 	}
 	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 @@
 		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 @@
 	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 @@
 
 	mutex_lock(&line->count_lock);
 
-	if (line->count) {
+	if (line->port.count) {
 		*error_out = "Device is already open";
 		goto out;
 	}
@@ -610,9 +615,15 @@
 	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 @@
 	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 0a18347..5b3d4fb 100644
--- a/arch/um/drivers/line.h
+++ b/arch/um/drivers/line.h
@@ -32,9 +32,8 @@
 };
 
 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 6cc4358..35819e3 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -1033,7 +1033,7 @@
 	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 @@
 	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 @@
 	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 @@
 		    (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 @@
 	}
 
 	if (new_serial.baud_base < 9600) {
-		tty_unlock();
+		tty_unlock(tty);
 		return -EINVAL;
 	}
 
@@ -1116,7 +1116,7 @@
 		}
 	} 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 e61cabd..69e9ca2 100644
--- a/drivers/tty/cyclades.c
+++ b/drivers/tty/cyclades.c
@@ -1599,7 +1599,7 @@
 	 * 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 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 @@
 		}
 		/* 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 @@
 
 		/* 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 @@
 		}
 
 		/* 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 @@
 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 @@
 	}
 	/* 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 @@
 			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 @@
 	}
 
 	/* 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 @@
 
 	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 5c6c314..1e64050 100644
--- a/drivers/tty/n_r3964.c
+++ b/drivers/tty/n_r3964.c
@@ -1065,7 +1065,7 @@
 
 	TRACE_L("read()");
 
-	tty_lock();
+	tty_lock(tty);
 
 	pClient = findClient(pInfo, task_pid(current));
 	if (pClient) {
@@ -1077,7 +1077,7 @@
 				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 @@
 	}
 	ret = -EPERM;
 unlock:
-	tty_unlock();
+	tty_unlock(tty);
 	return ret;
 }
 
@@ -1156,7 +1156,7 @@
 	pHeader->locks = 0;
 	pHeader->owner = NULL;
 
-	tty_lock();
+	tty_lock(tty);
 
 	pClient = findClient(pInfo, task_pid(current));
 	if (pClient) {
@@ -1175,7 +1175,7 @@
 	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 ee1c268..4f34491 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -1432,6 +1432,12 @@
 	 */
 	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 5505ffc..a0ca083 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -47,6 +47,7 @@
 	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 @@
 		        mutex_unlock(&devpts_mutex);
 		}
 #endif
-		tty_unlock();
+		tty_unlock(tty);
 		tty_vhangup(tty->link);
-		tty_lock();
+		tty_lock(tty);
 	}
 }
 
@@ -282,60 +283,98 @@
 	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;
+	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;
+		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 @@
 	.unthrottle = pty_unthrottle,
 	.set_termios = pty_set_termios,
 	.ioctl = pty_bsd_ioctl,
+	.cleanup = pty_cleanup,
 	.resize = pty_resize
 };
 
@@ -379,6 +419,7 @@
 	.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 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;
+	return pty_common_install(driver, tty, false);
 }
 
-static void ptm_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
-{
-}
-
-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 @@
 	.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 @@
 	.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 @@
 		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 @@
 	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 6e1958a..44f52c6 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -282,6 +282,14 @@
 		.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 @@
 	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 @@
 
 	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 @@
 
 	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 @@
 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_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 @@
 		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 @@
 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 f9719d1..c335b2b 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -78,6 +78,7 @@
 #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 b0ce8c5..8574983 100644
--- a/drivers/tty/serial/8250/8250_acorn.c
+++ b/drivers/tty/serial/8250/8250_acorn.c
@@ -43,7 +43,7 @@
 {
 	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 @@
 
 	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 f574eef..afb955f 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -89,7 +89,7 @@
 
 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 @@
 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
-	port.private_data = data;
+	uart.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 |
+	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 @@
 	}
 
 	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 d8c0ffb..097dff9 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 @@
 	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;
+	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_port(&port);
+	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 c13438c9..8f1dd2c 100644
--- a/drivers/tty/serial/8250/8250_hp300.c
+++ b/drivers/tty/serial/8250/8250_hp300.c
@@ -171,7 +171,7 @@
 		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 @@
 	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 @@
 #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 @@
 		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 28e7c7c..62e10fe 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -44,7 +44,7 @@
 	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 @@
 };
 
 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 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 @@
 		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 @@
  */
 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
 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_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 @@
 /* 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_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_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 @@
 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_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 @@
 
 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 @@
 	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_port *port, int idx)
+		  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_8250_port *port, int idx)
 {
 	unsigned int bar, offset = board->first_offset, maxnr;
 
@@ -1057,15 +1064,15 @@
 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 @@
 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 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_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 @@
 #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 @@
 		.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 @@
 	pbn_panacom,
 	pbn_panacom2,
 	pbn_panacom4,
-	pbn_exsys_4055,
 	pbn_plx_romulus,
 	pbn_oxsemi,
 	pbn_oxsemi_1_4000000,
@@ -2393,13 +2410,6 @@
 		.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 @@
 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 @@
 	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 @@
 	{	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 a2f2365..fde5aa6 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_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 @@
 			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 29b695d..b7d48b3 100644
--- a/drivers/tty/serial/8250/serial_cs.c
+++ b/drivers/tty/serial/8250/serial_cs.c
@@ -73,7 +73,7 @@
 	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 @@
  * 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 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 070b442..0020786 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -704,6 +704,25 @@
 	  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 7257c5d..8a5df38 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -34,6 +34,7 @@
 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 c17923e..b81cc31f 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1215,14 +1215,14 @@
 	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 @@
 }
 
 #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 @@
 	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 @@
 /*
  * 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 @@
 /*
  * 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 @@
 /*
  * 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 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 @@
 	.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 80b6b1b..7264d4d 100644
--- a/drivers/tty/serial/crisv10.c
+++ b/drivers/tty/serial/crisv10.c
@@ -3976,7 +3976,7 @@
 	 */
 	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 @@
 		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 @@
 	 */
 	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 4ef7473..0af4eec 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -207,7 +207,7 @@
 	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 0000000..ba3af3b
--- /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 5410c06..34e7187 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -208,6 +208,7 @@
 	{ .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 4fdec6a6..d291518 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -253,6 +253,9 @@
 	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 @@
 	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 @@
 		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 @@
 	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 @@
 
 	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 @@
 		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 @@
 {
 	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 @@
 
 	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 @@
 	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 @@
 	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 5847a4b..9033fc6 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -670,9 +670,19 @@
 {
 	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 @@
 	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 d8b0aee..d57f165 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -529,7 +529,7 @@
 
 	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 @@
 	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 @@
 	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 @@
 
 		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 @@
 {
 	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 @@
 	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 @@
 	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 @@
 	 * 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 @@
 	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 @@
 		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 @@
 		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 246b823..a21dc8e 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2527,14 +2527,16 @@
 	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 593d40a..5ed0daa 100644
--- a/drivers/tty/synclink.c
+++ b/drivers/tty/synclink.c
@@ -3338,9 +3338,9 @@
 			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 aa1debf..45b43f1 100644
--- a/drivers/tty/synclink_gt.c
+++ b/drivers/tty/synclink_gt.c
@@ -3336,9 +3336,9 @@
 		}
 
 		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 a3dddc1..4a1e4f0 100644
--- a/drivers/tty/synclinkmp.c
+++ b/drivers/tty/synclinkmp.c
@@ -3357,9 +3357,9 @@
 			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 b425c79..ca7c25d 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -185,6 +185,7 @@
 		put_device(tty->dev);
 	kfree(tty->write_buf);
 	tty_buffer_free_all(tty);
+	tty->magic = 0xDEADDEAD;
 	kfree(tty);
 }
 
@@ -573,7 +574,7 @@
 	}
 	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 @@
 	clear_bit(TTY_HUPPING, &tty->flags);
 	tty_ldisc_enable(tty);
 
-	tty_unlock();
+	tty_unlock(tty);
 
 	if (f)
 		fput(f);
@@ -1103,12 +1104,12 @@
 {
 	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 @@
 	}
 	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 @@
 	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 @@
 
 	/* 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 @@
 	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 @@
 	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 @@
 	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 @@
 		   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 @@
 
 		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 @@
 
 	/* 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 @@
 	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 @@
  *	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 @@
 	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 @@
 	}
 
 	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 @@
 		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 @@
 		/*
 		 * 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 @@
 	    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 @@
 
 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 @@
 	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 @@
 		kfree(p);
 		cdev_del(&driver->cdev);
 	}
+	kfree(driver->ports);
 	kfree(driver);
 }
 
@@ -3132,6 +3149,18 @@
 		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 @@
 		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 @@
 	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 @@
 	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 9911eb6..847f7ed 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -568,7 +568,7 @@
 	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 @@
 	 */
 
 	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 @@
 
 	tty_wait_until_sent(tty, 0);
 
-	tty_lock();
+	tty_lock(tty);
 	mutex_lock(&tty->ldisc_mutex);
 
 	/*
@@ -605,10 +605,10 @@
 
 	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 @@
 
 	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 @@
 
 	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 @@
 		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 @@
 	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 @@
 	 * 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 @@
 		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 @@
 	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 @@
 	 * 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();
+	if (o_tty) {
+		tty_ldisc_halt(o_tty);
+		tty_ldisc_flush_works(o_tty);
+	}
+	tty_lock_pair(tty, o_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);
-
-	/* 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 9ff986c..67feac9 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 bf6e238..a3ba776 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -33,6 +33,15 @@
 }
 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 @@
 
 	/* 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 @@
 			retval = -ERESTARTSYS;
 			break;
 		}
-		tty_unlock();
+		tty_unlock(tty);
 		schedule();
-		tty_lock();
+		tty_lock(tty);
 	}
 	finish_wait(&port->open_wait, &wait);
 
@@ -413,6 +422,14 @@
 }
 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 48cc6f2..9b4f60a 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -310,7 +310,7 @@
 
 	if (tty) {
 		tty_insert_flip_char(tty, ch, 0);
-		con_schedule_flip(tty);
+		tty_schedule_flip(tty);
 	}
 }
 
@@ -325,7 +325,7 @@
 		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 @@
 	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 @@
  */
 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 84cbf29..7cb53c2 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -1380,7 +1380,7 @@
 		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 @@
 /*
  * 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 @@
 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 6461854..b841f56 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -110,6 +110,34 @@
 		wake_up_interruptible(&vt_event_waitqueue);
 }
 
+static void __vt_event_queue(struct vt_event_wait *vw)
+{
+	unsigned long flags;
+	/* Prepare the event */
+	INIT_LIST_HEAD(&vw->list);
+	vw->done = 0;
+	/* Queue our event */
+	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);
+	spin_unlock_irqrestore(&vt_event_lock, flags);
+}
+
 /**
  *	vt_event_wait		-	wait for an event
  *	@vw: our event
@@ -121,20 +149,9 @@
 
 static void vt_event_wait(struct vt_event_wait *vw)
 {
-	unsigned long flags;
-	/* Prepare the event */
-	INIT_LIST_HEAD(&vw->list);
-	vw->done = 0;
-	/* Queue our event */
-	spin_lock_irqsave(&vt_event_lock, flags);
-	list_add(&vw->list, &vt_events);
-	spin_unlock_irqrestore(&vt_event_lock, flags);
-	/* Wait for it to pass */
-	wait_event_interruptible(vt_event_waitqueue, vw->done);
-	/* Dequeue it */
-	spin_lock_irqsave(&vt_event_lock, flags);
-	list_del(&vw->list);
-	spin_unlock_irqrestore(&vt_event_lock, flags);
+	__vt_event_queue(vw);
+	__vt_event_wait(vw);
+	__vt_event_dequeue(vw);
 }
 
 /**
@@ -177,10 +194,14 @@
 {
 	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 d47eb06..7ae9af6 100644
--- a/drivers/usb/serial/metro-usb.c
+++ b/drivers/usb/serial/metro-usb.c
@@ -130,20 +130,14 @@
 
 	/* 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 27483f9..da67abb 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -207,7 +207,7 @@
 	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 8760be3..cf41085 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -84,7 +84,6 @@
 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 += 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 += 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 1dc3ab0..0000000
--- 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 80093a8..0000000
--- 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 3f5ea8e..0000000
--- 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 79b3eb3..0000000
--- 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 ad700a6..0000000
--- 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 daf4a3a..af9137db 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -145,16 +145,4 @@
 
 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 7ca35ab..0000000
--- 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 59c81b7..0000000
--- 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 a416e92..f41dcc9 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -69,7 +69,6 @@
 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 65db992..0253c20 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 336af33c..0000000
--- 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 9f47ab5..7f9d7df 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -268,6 +268,7 @@
 	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 @@
 #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 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 @@
 
 /* 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 @@
 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 @@
  *
  * 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 @@
 		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 6e6dbb7..04419c1 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -313,6 +313,7 @@
 	 * 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 59ba38bc..80ffde3 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 @@
 	LOCAL_FLOW flow;          /* IrTTP flow status */
 
 	int line;
-	unsigned long flags;
 
 	__u8 dlsap_sel;
 	__u8 slsap_sel;
@@ -97,19 +91,10 @@
 	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 d1820ff..aa5d73b 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -710,9 +710,9 @@
 			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 8b915f3..3089391 100644
--- a/net/irda/ircomm/ircomm_param.c
+++ b/net/irda/ircomm/ircomm_param.c
@@ -99,7 +99,6 @@
  */
 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 @@
 	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 6b9d5a0..4e35b45 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -104,6 +104,35 @@
 #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 @@
 	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 @@
 
 	return 0;
 err:
-	clear_bit(ASYNC_B_INITIALIZED, &self->flags);
+	clear_bit(ASYNCB_INITIALIZED, &self->port.flags);
 	return ret;
 }
 
@@ -242,25 +271,23 @@
  *
  */
 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 @@
 
 	/* 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 @@
 		 * 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 @@
 		}
 
 		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 @@
 			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 @@
 		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 @@
 		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 @@
 		 * 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 @@
 	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 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__ );
+	if (tty_port_close_start(port, tty, filp) == 0)
 		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__ );
-		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 @@
 	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 @@
 	}
 
 	if (tty->hw_stopped)
-		return;
+		goto put;
 
 	/* Unlink transmit buffer */
 	spin_lock_irqsave(&self->spinlock, flags);
@@ -646,6 +606,8 @@
 
 	/* Check if user (still) wants to be waken up */
 	tty_wakeup(tty);
+put:
+	tty_kref_put(tty);
 }
 
 /*
@@ -955,7 +917,7 @@
 
 	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_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 @@
 	/* 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 @@
 	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 @@
 				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 @@
 				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 @@
 			}
 		}
 	}
+put:
+	tty_kref_put(tty);
 }
 
 /*
@@ -1128,6 +1096,7 @@
 				      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 @@
 	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 @@
 	 * 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 @@
 	 * 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 @@
 	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 @@
 	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 @@
 
 	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 b65d66e..3ab70e7 100644
--- a/net/irda/ircomm/ircomm_tty_attach.c
+++ b/net/irda/ircomm/ircomm_tty_attach.c
@@ -130,6 +130,8 @@
  */
 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 @@
 	}
 
 	/* 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 @@
 				      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_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 @@
 	 * 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 @@
 		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 d0667d6..0eab650 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 @@
 		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 @@
 
 	/* 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 @@
 		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 @@
 
 	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;