summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Documentation/serial/hayes-esp.txt154
-rw-r--r--Documentation/serial/tty.txt9
-rw-r--r--arch/xtensa/platforms/iss/console.c2
-rw-r--r--drivers/char/Kconfig13
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/bfin_jtag_comm.c2
-rw-r--r--drivers/char/epca.c2
-rw-r--r--drivers/char/esp.c2533
-rw-r--r--drivers/char/isicom.c115
-rw-r--r--drivers/char/istallion.c185
-rw-r--r--drivers/char/moxa.c289
-rw-r--r--drivers/char/mxser.c248
-rw-r--r--drivers/char/pcmcia/ipwireless/tty.c2
-rw-r--r--drivers/char/pty.c2
-rw-r--r--drivers/char/riscom8.c89
-rw-r--r--drivers/char/stallion.c129
-rw-r--r--drivers/char/tty_io.c151
-rw-r--r--drivers/char/tty_ldisc.c23
-rw-r--r--drivers/char/tty_port.c97
-rw-r--r--drivers/mmc/card/sdio_uart.c303
-rw-r--r--drivers/serial/8250.c24
-rw-r--r--drivers/serial/jsm/jsm.h8
-rw-r--r--drivers/serial/jsm/jsm_driver.c48
-rw-r--r--drivers/serial/jsm/jsm_neo.c8
-rw-r--r--drivers/serial/jsm/jsm_tty.c6
-rw-r--r--drivers/serial/pxa.c13
-rw-r--r--drivers/serial/serial_core.c33
-rw-r--r--drivers/usb/serial/opticon.c7
-rw-r--r--drivers/usb/serial/usb-serial.c83
-rw-r--r--fs/devpts/inode.c16
-rw-r--r--include/linux/Kbuild1
-rw-r--r--include/linux/hayesesp.h114
-rw-r--r--include/linux/isicom.h1
-rw-r--r--include/linux/tty.h25
-rw-r--r--include/linux/usb/serial.h3
-rw-r--r--kernel/exit.c2
36 files changed, 921 insertions, 3820 deletions
diff --git a/Documentation/serial/hayes-esp.txt b/Documentation/serial/hayes-esp.txt
deleted file mode 100644
index 09b5d5856758..000000000000
--- a/Documentation/serial/hayes-esp.txt
+++ /dev/null
@@ -1,154 +0,0 @@
-HAYES ESP DRIVER VERSION 2.1
-
-A big thanks to the people at Hayes, especially Alan Adamson.  Their support
-has enabled me to provide enhancements to the driver.
-
-Please report your experiences with this driver to me (arobinso@nyx.net).  I
-am looking for both positive and negative feedback.
-
-*** IMPORTANT CHANGES FOR 2.1 ***
-Support for PIO mode.  Five situations will cause PIO mode to be used:
-1) A multiport card is detected.  PIO mode will always be used.  (8 port cards
-do not support DMA).
-2) The DMA channel is set to an invalid value (anything other than 1 or 3).
-3) The DMA buffer/channel could not be allocated.  The port will revert to PIO
-mode until it is reopened.
-4) Less than a specified number of bytes need to be transferred to/from the
-FIFOs.  PIO mode will be used for that transfer only.
-5) A port needs to do a DMA transfer and another port is already using the
-DMA channel.  PIO mode will be used for that transfer only.
-
-Since the Hayes ESP seems to conflict with other cards (notably sound cards)
-when using DMA, DMA is turned off by default.  To use DMA, it must be turned
-on explicitly, either with the "dma=" option described below or with
-setserial.  A multiport card can be forced into DMA mode by using setserial;
-however, most multiport cards don't support DMA.
-
-The latest version of setserial allows the enhanced configuration of the ESP
-card to be viewed and modified.
-***
-
-This package contains the files needed to compile a module to support the Hayes
-ESP card.  The drivers are basically a modified version of the serial drivers.
-
-Features:
-
-- Uses the enhanced mode of the ESP card, allowing a wider range of
-  interrupts and features than compatibility mode
-- Uses DMA and 16 bit PIO mode to transfer data to and from the ESP's FIFOs,
-  reducing CPU load
-- Supports primary and secondary ports
-
-
-If the driver is compiled as a module, the IRQs to use can be specified by
-using the irq= option.  The format is:
-
-irq=[0x100],[0x140],[0x180],[0x200],[0x240],[0x280],[0x300],[0x380]
-
-The address in brackets is the base address of the card.  The IRQ of
-nonexistent cards can be set to 0.  If an IRQ of a card that does exist is set
-to 0, the driver will attempt to guess at the correct IRQ.  For example, to set
-the IRQ of the card at address 0x300 to 12, the insmod command would be:
-
-insmod esp irq=0,0,0,0,0,0,12,0
-
-The custom divisor can be set by using the divisor= option.  The format is the
-same as for the irq= option.  Each divisor value is a series of hex digits,
-with each digit representing the divisor to use for a corresponding port.  The
-divisor value is constructed RIGHT TO LEFT.  Specifying a nonzero divisor value
-will automatically set the spd_cust flag.  To calculate the divisor to use for
-a certain baud rate, divide the port's base baud (generally 921600) by the
-desired rate.  For example, to set the divisor of the primary port at 0x300 to
-4 and the divisor of the secondary port at 0x308 to 8, the insmod command would
-be:
-
-insmod esp divisor=0,0,0,0,0,0,0x84,0
-
-The dma= option can be used to set the DMA channel.  The channel can be either
-1 or 3.  Specifying any other value will force the driver to use PIO mode.
-For example, to set the DMA channel to 3, the insmod command would be:
-
-insmod esp dma=3
-
-The rx_trigger= and tx_trigger= options can be used to set the FIFO trigger
-levels.  They specify when the ESP card should send an interrupt.  Larger
-values will decrease the number of interrupts; however, a value too high may
-result in data loss.  Valid values are 1 through 1023, with 768 being the
-default.  For example, to set the receive trigger level to 512 bytes and the
-transmit trigger level to 700 bytes, the insmod command would be:
-
-insmod esp rx_trigger=512 tx_trigger=700
-
-The flow_off= and flow_on= options can be used to set the hardware flow off/
-flow on levels.  The flow on level must be lower than the flow off level, and
-the flow off level should be higher than rx_trigger.  Valid values are 1
-through 1023, with 1016 being the default flow off level and 944 being the
-default flow on level.  For example, to set the flow off level to 1000 bytes
-and the flow on level to 935 bytes, the insmod command would be:
-
-insmod esp flow_off=1000 flow_on=935
-
-The rx_timeout= option can be used to set the receive timeout value.  This
-value indicates how long after receiving the last character that the ESP card
-should wait before signalling an interrupt.  Valid values are 0 though 255,
-with 128 being the default.  A value too high will increase latency, and a
-value too low will cause unnecessary interrupts.  For example, to set the
-receive timeout to 255, the insmod command would be:
-
-insmod esp rx_timeout=255
-
-The pio_threshold= option sets the threshold (in number of characters) for
-using PIO mode instead of DMA mode.  For example, if this value is 32,
-transfers of 32 bytes or less will always use PIO mode.
-
-insmod esp pio_threshold=32
-
-Multiple options can be listed on the insmod command line by separating each
-option with a space.  For example:
-
-insmod esp dma=3 trigger=512
-
-The esp module can be automatically loaded when needed.  To cause this to
-happen, add the following lines to /etc/modprobe.conf (replacing the last line
-with options for your configuration):
-
-alias char-major-57 esp
-alias char-major-58 esp
-options esp irq=0,0,0,0,0,0,3,0 divisor=0,0,0,0,0,0,0x4,0
-
-You may also need to run 'depmod -a'.
-
-Devices must be created manually.  To create the devices, note the output from
-the module after it is inserted.  The output will appear in the location where
-kernel messages usually appear (usually /var/adm/messages).  Create two devices
-for each 'tty' mentioned, one with major of 57 and the other with major of 58.
-The minor number should be the same as the tty number reported.  The commands
-would be (replace ? with the tty number):
-
-mknod /dev/ttyP? c 57 ?
-mknod /dev/cup? c 58 ?
-
-For example, if the following line appears:
-
-Oct 24 18:17:23 techno kernel: ttyP8 at 0x0140 (irq = 3) is an ESP primary port
-
-...two devices should be created:
-
-mknod /dev/ttyP8 c 57 8
-mknod /dev/cup8 c 58 8
-
-You may need to set the permissions on the devices:
-
-chmod 666 /dev/ttyP*
-chmod 666 /dev/cup*
-
-The ESP module and the serial module should not conflict (they can be used at
-the same time).  After the ESP module has been loaded the ports on the ESP card
-will no longer be accessible by the serial driver.
-
-If I/O errors are experienced when accessing the port, check for IRQ and DMA
-conflicts ('cat /proc/interrupts' and 'cat /proc/dma' for a list of IRQs and
-DMAs currently in use).
-
-Enjoy!
-Andrew J. Robinson <arobinso@nyx.net>
diff --git a/Documentation/serial/tty.txt b/Documentation/serial/tty.txt
index 8e65c4498c52..5e5349a4fcd2 100644
--- a/Documentation/serial/tty.txt
+++ b/Documentation/serial/tty.txt
@@ -42,7 +42,8 @@ TTY side interfaces:
 open()		-	Called when the line discipline is attached to
 			the terminal. No other call into the line
 			discipline for this tty will occur until it
-			completes successfully. Can sleep.
+			completes successfully. Returning an error will
+			prevent the ldisc from being attached. Can sleep.
 
 close()		-	This is called on a terminal when the line
 			discipline is being unplugged. At the point of
@@ -52,7 +53,7 @@ close()		-	This is called on a terminal when the line
 hangup()	-	Called when the tty line is hung up.
 			The line discipline should cease I/O to the tty.
 			No further calls into the ldisc code will occur.
-			Can sleep.
+			The return value is ignored. Can sleep.
 
 write()		-	A process is writing data through the line
 			discipline.  Multiple write calls are serialized
@@ -83,6 +84,10 @@ ioctl()		-	Called when an ioctl is handed to the tty layer
 			that might be for the ldisc. Multiple ioctl calls
 			may occur in parallel. May sleep. 
 
+compat_ioctl()	-	Called when a 32 bit ioctl is handed to the tty layer
+			that might be for the ldisc. Multiple ioctl calls
+			may occur in parallel. May sleep.
+
 Driver Side Interfaces:
 
 receive_buf()	-	Hand buffers of bytes from the driver to the ldisc
diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c
index 4c559cf7da2d..e60a1f57022f 100644
--- a/arch/xtensa/platforms/iss/console.c
+++ b/arch/xtensa/platforms/iss/console.c
@@ -196,7 +196,7 @@ static const struct file_operations rs_proc_fops = {
 	.release	= single_release,
 };
 
-static struct tty_operations serial_ops = {
+static const struct tty_operations serial_ops = {
 	.open = rs_open,
 	.close = rs_close,
 	.write = rs_write,
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 6aad99ec4e0f..6f31c9472100 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -201,19 +201,6 @@ config DIGIEPCA
 	  To compile this driver as a module, choose M here: the
 	  module will be called epca.
 
-config ESPSERIAL
-	tristate "Hayes ESP serial port support"
-	depends on SERIAL_NONSTANDARD && ISA && ISA_DMA_API && BROKEN
-	help
-	  This is a driver which supports Hayes ESP serial ports.  Both single
-	  port cards and multiport cards are supported.  Make sure to read
-	  <file:Documentation/hayes-esp.txt>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called esp.
-
-	  If unsure, say N.
-
 config MOXA_INTELLIO
 	tristate "Moxa Intellio support"
 	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 19a79dd79eee..f957edf7e45d 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -18,7 +18,6 @@ obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o
 obj-$(CONFIG_HW_CONSOLE)	+= vt.o defkeymap.o
 obj-$(CONFIG_AUDIT)		+= tty_audit.o
 obj-$(CONFIG_MAGIC_SYSRQ)	+= sysrq.o
-obj-$(CONFIG_ESPSERIAL)		+= esp.o
 obj-$(CONFIG_MVME147_SCC)	+= generic_serial.o vme_scc.o
 obj-$(CONFIG_MVME162_SCC)	+= generic_serial.o vme_scc.o
 obj-$(CONFIG_BVME6000_SCC)	+= generic_serial.o vme_scc.o
diff --git a/drivers/char/bfin_jtag_comm.c b/drivers/char/bfin_jtag_comm.c
index 1d7c34c73b20..2628c7415ea8 100644
--- a/drivers/char/bfin_jtag_comm.c
+++ b/drivers/char/bfin_jtag_comm.c
@@ -226,7 +226,7 @@ bfin_jc_wait_until_sent(struct tty_struct *tty, int timeout)
 	}
 }
 
-static struct tty_operations bfin_jc_ops = {
+static const struct tty_operations bfin_jc_ops = {
 	.open            = bfin_jc_open,
 	.close           = bfin_jc_close,
 	.write           = bfin_jc_write,
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index dde5134713e2..17b044a71e02 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -935,7 +935,7 @@ static int info_open(struct tty_struct *tty, struct file *filp)
 	return 0;
 }
 
-static struct tty_operations info_ops = {
+static const struct tty_operations info_ops = {
 	.open = info_open,
 	.ioctl = info_ioctl,
 };
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
deleted file mode 100644
index b19d43cd9542..000000000000
--- a/drivers/char/esp.c
+++ /dev/null
@@ -1,2533 +0,0 @@
-/*
- *  esp.c - driver for Hayes ESP serial cards
- *
- *  --- Notices from serial.c, upon which this driver is based ---
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- *  Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92.  Now
- *  much more extensible to support other serial cards based on the
- *  16450/16550A UART's.  Added support for the AST FourPort and the
- *  Accent Async board.
- *
- *  set_serial_info fixed to set the flags, custom divisor, and uart
- * 	type fields.  Fix suggested by Michael K. Johnson 12/12/92.
- *
- *  11/95: TIOCMIWAIT, TIOCGICOUNT by Angelo Haritsis <ah@doc.ic.ac.uk>
- *
- *  03/96: Modularised by Angelo Haritsis <ah@doc.ic.ac.uk>
- *
- *  rs_set_termios fixed to look also for changes of the input
- *      flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK.
- *                                            Bernd Anhäupl 05/17/96.
- *
- * --- End of notices from serial.c ---
- *
- * Support for the ESP serial card by Andrew J. Robinson
- *     <arobinso@nyx.net> (Card detection routine taken from a patch
- *     by Dennis J. Boylan).  Patches to allow use with 2.1.x contributed
- *     by Chris Faylor.
- *
- * Most recent changes: (Andrew J. Robinson)
- *   Support for PIO mode.  This allows the driver to work properly with
- *     multiport cards.
- *
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br> -
- * several cleanups, use module_init/module_exit, etc
- *
- * This module exports the following rs232 io functions:
- *
- *	int espserial_init(void);
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <linux/io.h>
-
-#include <asm/dma.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-#include <linux/hayesesp.h>
-
-#define NR_PORTS 64	/* maximum number of ports */
-#define NR_PRIMARY 8	/* maximum number of primary ports */
-#define REGION_SIZE 8   /* size of io region to request */
-
-/* The following variables can be set by giving module options */
-static int irq[NR_PRIMARY];	/* IRQ for each base port */
-static unsigned int divisor[NR_PRIMARY]; /* custom divisor for each port */
-static unsigned int dma = ESP_DMA_CHANNEL; /* DMA channel */
-static unsigned int rx_trigger = ESP_RX_TRIGGER;
-static unsigned int tx_trigger = ESP_TX_TRIGGER;
-static unsigned int flow_off = ESP_FLOW_OFF;
-static unsigned int flow_on = ESP_FLOW_ON;
-static unsigned int rx_timeout = ESP_RX_TMOUT;
-static unsigned int pio_threshold = ESP_PIO_THRESHOLD;
-
-MODULE_LICENSE("GPL");
-
-module_param_array(irq, int, NULL, 0);
-module_param_array(divisor, uint, NULL, 0);
-module_param(dma, uint, 0);
-module_param(rx_trigger, uint, 0);
-module_param(tx_trigger, uint, 0);
-module_param(flow_off, uint, 0);
-module_param(flow_on, uint, 0);
-module_param(rx_timeout, uint, 0);
-module_param(pio_threshold, uint, 0);
-
-/* END */
-
-static char *dma_buffer;
-static int dma_bytes;
-static struct esp_pio_buffer *free_pio_buf;
-
-#define DMA_BUFFER_SZ 1024
-
-#define WAKEUP_CHARS 1024
-
-static char serial_name[] __initdata = "ESP serial driver";
-static char serial_version[] __initdata = "2.2";
-
-static struct tty_driver *esp_driver;
-
-/*
- * Serial driver configuration section.  Here are the various options:
- *
- * SERIAL_PARANOIA_CHECK
- * 		Check the magic number for the esp_structure where
- * 		ever possible.
- */
-
-#undef SERIAL_PARANOIA_CHECK
-#define SERIAL_DO_RESTART
-
-#undef SERIAL_DEBUG_INTR
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_FLOW
-
-#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
-#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
-				tty->name, info->port.flags, \
-				serial_driver.refcount, \
-				info->port.count, tty->count, s)
-#else
-#define DBG_CNT(s)
-#endif
-
-static struct esp_struct *ports;
-
-static void change_speed(struct esp_struct *info);
-static void rs_wait_until_sent(struct tty_struct *, int);
-
-/*
- * The ESP card has a clock rate of 14.7456 MHz (that is, 2**ESPC_SCALE
- * times the normal 1.8432 Mhz clock of most serial boards).
- */
-#define BASE_BAUD ((1843200 / 16) * (1 << ESPC_SCALE))
-
-/* Standard COM flags (except for COM4, because of the 8514 problem) */
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-
-static inline int serial_paranoia_check(struct esp_struct *info,
-					char *name, const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
-	static const char badmagic[] = KERN_WARNING
-		"Warning: bad magic number for serial struct (%s) in %s\n";
-	static const char badinfo[] = KERN_WARNING
-		"Warning: null esp_struct for (%s) in %s\n";
-
-	if (!info) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (info->magic != ESP_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-static inline unsigned int serial_in(struct esp_struct *info, int offset)
-{
-	return inb(info->io_port + offset);
-}
-
-static inline void serial_out(struct esp_struct *info, int offset,
-			      unsigned char value)
-{
-	outb(value, info->io_port+offset);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_stop() and rs_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- * ------------------------------------------------------------
- */
-static void rs_stop(struct tty_struct *tty)
-{
-	struct esp_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_stop"))
-		return;
-
-	spin_lock_irqsave(&info->lock, flags);
-	if (info->IER & UART_IER_THRI) {
-		info->IER &= ~UART_IER_THRI;
-		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
-		serial_out(info, UART_ESI_CMD2, info->IER);
-	}
-	spin_unlock_irqrestore(&info->lock, flags);
-}
-
-static void rs_start(struct tty_struct *tty)
-{
-	struct esp_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_start"))
-		return;
-
-	spin_lock_irqsave(&info->lock, flags);
-	if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) {
-		info->IER |= UART_IER_THRI;
-		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
-		serial_out(info, UART_ESI_CMD2, info->IER);
-	}
-	spin_unlock_irqrestore(&info->lock, flags);
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * Here starts the interrupt handling routines.  All of the following
- * subroutines are declared as inline and are folded into
- * rs_interrupt().  They were separated out for readability's sake.
- *
- * Note: rs_interrupt() is a "fast" interrupt, which means that it
- * runs with interrupts turned off.  People who may want to modify
- * rs_interrupt() should try to keep the interrupt handler as fast as
- * possible.  After you are done making modifications, it is not a bad
- * idea to do:
- *
- * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
- *
- * and look at the resulting assemble code in serial.s.
- *
- * 				- Ted Ts'o (tytso@mit.edu), 7-Mar-93
- * -----------------------------------------------------------------------
- */
-
-static DEFINE_SPINLOCK(pio_lock);
-
-static inline struct esp_pio_buffer *get_pio_buffer(void)
-{
-	struct esp_pio_buffer *buf;
-	unsigned long flags;
-
-	spin_lock_irqsave(&pio_lock, flags);
-	if (free_pio_buf) {
-		buf = free_pio_buf;
-		free_pio_buf = buf->next;
-	} else {
-		buf = kmalloc(sizeof(struct esp_pio_buffer), GFP_ATOMIC);
-	}
-	spin_unlock_irqrestore(&pio_lock, flags);
-	return buf;
-}
-
-static inline void release_pio_buffer(struct esp_pio_buffer *buf)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&pio_lock, flags);
-	buf->next = free_pio_buf;
-	free_pio_buf = buf;
-	spin_unlock_irqrestore(&pio_lock, flags);
-}
-
-static inline void receive_chars_pio(struct esp_struct *info, int num_bytes)
-{
-	struct tty_struct *tty = info->port.tty;
-	int i;
-	struct esp_pio_buffer *pio_buf;
-	struct esp_pio_buffer *err_buf;
-	unsigned char status_mask;
-
-	pio_buf = get_pio_buffer();
-
-	if (!pio_buf)
-		return;
-
-	err_buf = get_pio_buffer();
-
-	if (!err_buf) {
-		release_pio_buffer(pio_buf);
-		return;
-	}
-
-	status_mask = (info->read_status_mask >> 2) & 0x07;
-
-	for (i = 0; i < num_bytes - 1; i += 2) {
-		*((unsigned short *)(pio_buf->data + i)) =
-			inw(info->io_port + UART_ESI_RX);
-		err_buf->data[i] = serial_in(info, UART_ESI_RWS);
-		err_buf->data[i + 1] = (err_buf->data[i] >> 3) & status_mask;
-		err_buf->data[i] &= status_mask;
-	}
-
-	if (num_bytes & 0x0001) {
-		pio_buf->data[num_bytes - 1] = serial_in(info, UART_ESI_RX);
-		err_buf->data[num_bytes - 1] =
-			(serial_in(info, UART_ESI_RWS) >> 3) & status_mask;
-	}
-
-	/* make sure everything is still ok since interrupts were enabled */
-	tty = info->port.tty;
-
-	if (!tty) {
-		release_pio_buffer(pio_buf);
-		release_pio_buffer(err_buf);
-		info->stat_flags &= ~ESP_STAT_RX_TIMEOUT;
-		return;
-	}
-
-	status_mask = (info->ignore_status_mask >> 2) & 0x07;
-
-	for (i = 0; i < num_bytes; i++) {
-		if (!(err_buf->data[i] & status_mask)) {
-			int flag = 0;
-
-			if (err_buf->data[i] & 0x04) {
-				flag = TTY_BREAK;
-				if (info->port.flags & ASYNC_SAK)
-					do_SAK(tty);
-			} else if (err_buf->data[i] & 0x02)
-				flag = TTY_FRAME;
-			else if (err_buf->data[i] & 0x01)
-				flag = TTY_PARITY;
-			tty_insert_flip_char(tty, pio_buf->data[i], flag);
-		}
-	}
-
-	tty_schedule_flip(tty);
-
-	info->stat_flags &= ~ESP_STAT_RX_TIMEOUT;
-	release_pio_buffer(pio_buf);
-	release_pio_buffer(err_buf);
-}
-
-static void program_isa_dma(int dma, int dir, unsigned long addr, int len)
-{
-	unsigned long flags;
-
-	flags = claim_dma_lock();
-	disable_dma(dma);
-	clear_dma_ff(dma);
-	set_dma_mode(dma, dir);
-	set_dma_addr(dma, addr);
-	set_dma_count(dma, len);
-	enable_dma(dma);
-	release_dma_lock(flags);
-}
-
-static void receive_chars_dma(struct esp_struct *info, int num_bytes)
-{
-	info->stat_flags &= ~ESP_STAT_RX_TIMEOUT;
-	dma_bytes = num_bytes;
-	info->stat_flags |= ESP_STAT_DMA_RX;
-
-	program_isa_dma(dma, DMA_MODE_READ, isa_virt_to_bus(dma_buffer),
-								dma_bytes);
-	serial_out(info, UART_ESI_CMD1, ESI_START_DMA_RX);
-}
-
-static inline void receive_chars_dma_done(struct esp_struct *info,
-					    int status)
-{
-	struct tty_struct *tty = info->port.tty;
-	int num_bytes;
-	unsigned long flags;
-
-	flags = claim_dma_lock();
-	disable_dma(dma);
-	clear_dma_ff(dma);
-
-	info->stat_flags &= ~ESP_STAT_DMA_RX;
-	num_bytes = dma_bytes - get_dma_residue(dma);
-	release_dma_lock(flags);
-
-	info->icount.rx += num_bytes;
-
-	if (num_bytes > 0) {
-		tty_insert_flip_string(tty, dma_buffer, num_bytes - 1);
-
-		status &= (0x1c & info->read_status_mask);
-
-		/* Is the status significant or do we throw the last byte ? */
-		if (!(status & info->ignore_status_mask)) {
-			int statflag = 0;
-
-			if (status & 0x10) {
-				statflag = TTY_BREAK;
-				(info->icount.brk)++;
-				if (info->port.flags & ASYNC_SAK)
-					do_SAK(tty);
-			} else if (status & 0x08) {
-				statflag = TTY_FRAME;
-				info->icount.frame++;
-			} else if (status & 0x04) {
-				statflag = TTY_PARITY;
-				info->icount.parity++;
-			}
-			tty_insert_flip_char(tty, dma_buffer[num_bytes - 1],
-								statflag);
-		}
-		tty_schedule_flip(tty);
-	}
-
-	if (dma_bytes != num_bytes) {
-		num_bytes = dma_bytes - num_bytes;
-		dma_bytes = 0;
-		receive_chars_dma(info, num_bytes);
-	} else
-		dma_bytes = 0;
-}
-
-/* Caller must hold info->lock */
-
-static inline void transmit_chars_pio(struct esp_struct *info,
-					int space_avail)
-{
-	int i;
-	struct esp_pio_buffer *pio_buf;
-
-	pio_buf = get_pio_buffer();
-
-	if (!pio_buf)
-		return;
-
-	while (space_avail && info->xmit_cnt) {
-		if (info->xmit_tail + space_avail <= ESP_XMIT_SIZE) {
-			memcpy(pio_buf->data,
-			       &(info->xmit_buf[info->xmit_tail]),
-			       space_avail);
-		} else {
-			i = ESP_XMIT_SIZE - info->xmit_tail;
-			memcpy(pio_buf->data,
-			       &(info->xmit_buf[info->xmit_tail]), i);
-			memcpy(&(pio_buf->data[i]), info->xmit_buf,
-			       space_avail - i);
-		}
-
-		info->xmit_cnt -= space_avail;
-		info->xmit_tail = (info->xmit_tail + space_avail) &
-			(ESP_XMIT_SIZE - 1);
-
-		for (i = 0; i < space_avail - 1; i += 2) {
-			outw(*((unsigned short *)(pio_buf->data + i)),
-			     info->io_port + UART_ESI_TX);
-		}
-
-		if (space_avail & 0x0001)
-			serial_out(info, UART_ESI_TX,
-				   pio_buf->data[space_avail - 1]);
-
-		if (info->xmit_cnt) {
-			serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
-			serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
-			space_avail = serial_in(info, UART_ESI_STAT1) << 8;
-			space_avail |= serial_in(info, UART_ESI_STAT2);
-
-			if (space_avail > info->xmit_cnt)
-				space_avail = info->xmit_cnt;
-		}
-	}
-
-	if (info->xmit_cnt < WAKEUP_CHARS) {
-		if (info->port.tty)
-			tty_wakeup(info->port.tty);
-
-#ifdef SERIAL_DEBUG_INTR
-		printk("THRE...");
-#endif
-
-		if (info->xmit_cnt <= 0) {
-			info->IER &= ~UART_IER_THRI;
-			serial_out(info, UART_ESI_CMD1,
-				   ESI_SET_SRV_MASK);
-			serial_out(info, UART_ESI_CMD2, info->IER);
-		}
-	}
-
-	release_pio_buffer(pio_buf);
-}
-
-/* Caller must hold info->lock */
-static inline void transmit_chars_dma(struct esp_struct *info, int num_bytes)
-{
-	dma_bytes = num_bytes;
-
-	if (info->xmit_tail + dma_bytes <= ESP_XMIT_SIZE) {
-		memcpy(dma_buffer, &(info->xmit_buf[info->xmit_tail]),
-		       dma_bytes);
-	} else {
-		int i = ESP_XMIT_SIZE - info->xmit_tail;
-		memcpy(dma_buffer, &(info->xmit_buf[info->xmit_tail]),
-			i);
-		memcpy(&(dma_buffer[i]), info->xmit_buf, dma_bytes - i);
-	}
-
-	info->xmit_cnt -= dma_bytes;
-	info->xmit_tail = (info->xmit_tail + dma_bytes) & (ESP_XMIT_SIZE - 1);
-
-	if (info->xmit_cnt < WAKEUP_CHARS) {
-		if (info->port.tty)
-			tty_wakeup(info->port.tty);
-
-#ifdef SERIAL_DEBUG_INTR
-		printk("THRE...");
-#endif
-
-		if (info->xmit_cnt <= 0) {
-			info->IER &= ~UART_IER_THRI;
-			serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
-			serial_out(info, UART_ESI_CMD2, info->IER);
-		}
-	}
-
-	info->stat_flags |= ESP_STAT_DMA_TX;
-
-	program_isa_dma(dma, DMA_MODE_WRITE, isa_virt_to_bus(dma_buffer),
-								dma_bytes);
-	serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);
-}
-
-static inline void transmit_chars_dma_done(struct esp_struct *info)
-{
-	int num_bytes;
-	unsigned long flags;
-
-	flags = claim_dma_lock();
-	disable_dma(dma);
-	clear_dma_ff(dma);
-
-	num_bytes = dma_bytes - get_dma_residue(dma);
-	info->icount.tx += dma_bytes;
-	release_dma_lock(flags);
-
-	if (dma_bytes != num_bytes) {
-		dma_bytes -= num_bytes;
-		memmove(dma_buffer, dma_buffer + num_bytes, dma_bytes);
-
-		program_isa_dma(dma, DMA_MODE_WRITE,
-				isa_virt_to_bus(dma_buffer), dma_bytes);
-
-		serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);
-	} else {
-		dma_bytes = 0;
-		info->stat_flags &= ~ESP_STAT_DMA_TX;
-	}
-}
-
-static void check_modem_status(struct esp_struct *info)
-{
-	int	status;
-
-	serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
-	status = serial_in(info, UART_ESI_STAT2);
-
-	if (status & UART_MSR_ANY_DELTA) {
-		/* update input line counters */
-		if (status & UART_MSR_TERI)
-			info->icount.rng++;
-		if (status & UART_MSR_DDSR)
-			info->icount.dsr++;
-		if (status & UART_MSR_DDCD)
-			info->icount.dcd++;
-		if (status & UART_MSR_DCTS)
-			info->icount.cts++;
-		wake_up_interruptible(&info->port.delta_msr_wait);
-	}
-
-	if ((info->port.flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
-#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
-		printk("ttys%d CD now %s...", info->line,
-		       (status & UART_MSR_DCD) ? "on" : "off");
-#endif
-		if (status & UART_MSR_DCD)
-			wake_up_interruptible(&info->port.open_wait);
-		else {
-#ifdef SERIAL_DEBUG_OPEN
-			printk("scheduling hangup...");
-#endif
-			tty_hangup(info->port.tty);
-		}
-	}
-}
-
-/*
- * This is the serial driver's interrupt routine
- */
-static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
-{
-	struct esp_struct *info;
-	unsigned err_status;
-	unsigned int scratch;
-
-#ifdef SERIAL_DEBUG_INTR
-	printk("rs_interrupt_single(%d)...", irq);
-#endif
-	info = (struct esp_struct *)dev_id;
-	err_status = 0;
-	scratch = serial_in(info, UART_ESI_SID);
-
-	spin_lock(&info->lock);
-
-	if (!info->port.tty) {
-		spin_unlock(&info->lock);
-		return IRQ_NONE;
-	}
-
-	if (scratch & 0x04) { /* error */
-		serial_out(info, UART_ESI_CMD1, ESI_GET_ERR_STAT);
-		err_status = serial_in(info, UART_ESI_STAT1);
-		serial_in(info, UART_ESI_STAT2);
-
-		if (err_status & 0x01)
-			info->stat_flags |= ESP_STAT_RX_TIMEOUT;
-
-		if (err_status & 0x20) /* UART status */
-			check_modem_status(info);
-
-		if (err_status & 0x80) /* Start break */
-			wake_up_interruptible(&info->break_wait);
-	}
-
-	if ((scratch & 0x88) || /* DMA completed or timed out */
-	    (err_status & 0x1c) /* receive error */) {
-		if (info->stat_flags & ESP_STAT_DMA_RX)
-			receive_chars_dma_done(info, err_status);
-		else if (info->stat_flags & ESP_STAT_DMA_TX)
-			transmit_chars_dma_done(info);
-	}
-
-	if (!(info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) &&
-	    ((scratch & 0x01) || (info->stat_flags & ESP_STAT_RX_TIMEOUT)) &&
-	    (info->IER & UART_IER_RDI)) {
-		int num_bytes;
-
-		serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
-		serial_out(info, UART_ESI_CMD1, ESI_GET_RX_AVAIL);
-		num_bytes = serial_in(info, UART_ESI_STAT1) << 8;
-		num_bytes |= serial_in(info, UART_ESI_STAT2);
-
-		num_bytes = tty_buffer_request_room(info->port.tty, num_bytes);
-
-		if (num_bytes) {
-			if (dma_bytes ||
-			    (info->stat_flags & ESP_STAT_USE_PIO) ||
-			    (num_bytes <= info->config.pio_threshold))
-				receive_chars_pio(info, num_bytes);
-			else
-				receive_chars_dma(info, num_bytes);
-		}
-	}
-
-	if (!(info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) &&
-	    (scratch & 0x02) && (info->IER & UART_IER_THRI)) {
-		if ((info->xmit_cnt <= 0) || info->port.tty->stopped) {
-			info->IER &= ~UART_IER_THRI;
-			serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
-			serial_out(info, UART_ESI_CMD2, info->IER);
-		} else {
-			int num_bytes;
-
-			serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
-			serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
-			num_bytes = serial_in(info, UART_ESI_STAT1) << 8;
-			num_bytes |= serial_in(info, UART_ESI_STAT2);
-
-			if (num_bytes > info->xmit_cnt)
-				num_bytes = info->xmit_cnt;
-
-			if (num_bytes) {
-				if (dma_bytes ||
-				    (info->stat_flags & ESP_STAT_USE_PIO) ||
-				    (num_bytes <= info->config.pio_threshold))
-					transmit_chars_pio(info, num_bytes);
-				else
-					transmit_chars_dma(info, num_bytes);
-			}
-		}
-	}
-
-	info->last_active = jiffies;
-
-#ifdef SERIAL_DEBUG_INTR
-	printk("end.\n");
-#endif
-	spin_unlock(&info->lock);
-	return IRQ_HANDLED;
-}
-
-/*
- * -------------------------------------------------------------------
- * Here ends the serial interrupt routines.
- * -------------------------------------------------------------------
- */
-
-/*
- * ---------------------------------------------------------------
- * Low level utility subroutines for the serial driver:  routines to
- * figure out the appropriate timeout for an interrupt chain, routines
- * to initialize and startup a serial port, and routines to shutdown a
- * serial port.  Useful stuff like that.
- *
- * Caller should hold lock
- * ---------------------------------------------------------------
- */
-
-static void esp_basic_init(struct esp_struct *info)
-{
-	/* put ESPC in enhanced mode */
-	serial_out(info, UART_ESI_CMD1, ESI_SET_MODE);
-
-	if (info->stat_flags & ESP_STAT_NEVER_DMA)
-		serial_out(info, UART_ESI_CMD2, 0x01);
-	else
-		serial_out(info, UART_ESI_CMD2, 0x31);
-
-	/* disable interrupts for now */
-	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
-	serial_out(info, UART_ESI_CMD2, 0x00);
-
-	/* set interrupt and DMA channel */
-	serial_out(info, UART_ESI_CMD1, ESI_SET_IRQ);
-
-	if (info->stat_flags & ESP_STAT_NEVER_DMA)
-		serial_out(info, UART_ESI_CMD2, 0x01);
-	else
-		serial_out(info, UART_ESI_CMD2, (dma << 4) | 0x01);
-
-	serial_out(info, UART_ESI_CMD1, ESI_SET_ENH_IRQ);
-
-	if (info->line % 8)	/* secondary port */
-		serial_out(info, UART_ESI_CMD2, 0x0d);	/* shared */
-	else if (info->irq == 9)
-		serial_out(info, UART_ESI_CMD2, 0x02);
-	else
-		serial_out(info, UART_ESI_CMD2, info->irq);
-
-	/* set error status mask (check this) */
-	serial_out(info, UART_ESI_CMD1, ESI_SET_ERR_MASK);
-
-	if (info->stat_flags & ESP_STAT_NEVER_DMA)
-		serial_out(info, UART_ESI_CMD2, 0xa1);
-	else
-		serial_out(info, UART_ESI_CMD2, 0xbd);
-
-	serial_out(info, UART_ESI_CMD2, 0x00);
-
-	/* set DMA timeout */
-	serial_out(info, UART_ESI_CMD1, ESI_SET_DMA_TMOUT);
-	serial_out(info, UART_ESI_CMD2, 0xff);
-
-	/* set FIFO trigger levels */
-	serial_out(info, UART_ESI_CMD1, ESI_SET_TRIGGER);
-	serial_out(info, UART_ESI_CMD2, info->config.rx_trigger >> 8);
-	serial_out(info, UART_ESI_CMD2, info->config.rx_trigger);
-	serial_out(info, UART_ESI_CMD2, info->config.tx_trigger >> 8);
-	serial_out(info, UART_ESI_CMD2, info->config.tx_trigger);
-
-	/* Set clock scaling and wait states */
-	serial_out(info, UART_ESI_CMD1, ESI_SET_PRESCALAR);
-	serial_out(info, UART_ESI_CMD2, 0x04 | ESPC_SCALE);
-
-	/* set reinterrupt pacing */
-	serial_out(info, UART_ESI_CMD1, ESI_SET_REINTR);
-	serial_out(info, UART_ESI_CMD2, 0xff);
-}
-
-static int startup(struct esp_struct *info)
-{
-	unsigned long flags;
-	int	retval = 0;
-	unsigned int num_chars;
-
-	spin_lock_irqsave(&info->lock, flags);
-
-	if (info->port.flags & ASYNC_INITIALIZED)
-		goto out;
-
-	if (!info->xmit_buf) {
-		info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_ATOMIC);
-		retval = -ENOMEM;
-		if (!info->xmit_buf)
-			goto out;
-	}
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk(KERN_DEBUG "starting up ttys%d (irq %d)...",
-						info->line, info->irq);
-#endif
-
-	/* Flush the RX buffer.  Using the ESI flush command may cause */
-	/* wild interrupts, so read all the data instead. */
-
-	serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
-	serial_out(info, UART_ESI_CMD1, ESI_GET_RX_AVAIL);
-	num_chars = serial_in(info, UART_ESI_STAT1) << 8;
-	num_chars |= serial_in(info, UART_ESI_STAT2);
-
-	while (num_chars > 1) {
-		inw(info->io_port + UART_ESI_RX);
-		num_chars -= 2;
-	}
-
-	if (num_chars)
-		serial_in(info, UART_ESI_RX);
-
-	/* set receive character timeout */
-	serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);
-	serial_out(info, UART_ESI_CMD2, info->config.rx_timeout);
-
-	/* clear all flags except the "never DMA" flag */
-	info->stat_flags &= ESP_STAT_NEVER_DMA;
-
-	if (info->stat_flags & ESP_STAT_NEVER_DMA)
-		info->stat_flags |= ESP_STAT_USE_PIO;
-
-	spin_unlock_irqrestore(&info->lock, flags);
-
-	/*
-	 * Allocate the IRQ
-	 */
-
-	retval = request_irq(info->irq, rs_interrupt_single, IRQF_SHARED,
-			     "esp serial", info);
-
-	if (retval) {
-		if (capable(CAP_SYS_ADMIN)) {
-			if (info->port.tty)
-				set_bit(TTY_IO_ERROR,
-					&info->port.tty->flags);
-			retval = 0;
-		}
-		goto out_unlocked;
-	}
-
-	if (!(info->stat_flags & ESP_STAT_USE_PIO) && !dma_buffer) {
-		dma_buffer = (char *)__get_dma_pages(
-			GFP_KERNEL, get_order(DMA_BUFFER_SZ));
-
-		/* use PIO mode if DMA buf/chan cannot be allocated */
-		if (!dma_buffer)
-			info->stat_flags |= ESP_STAT_USE_PIO;
-		else if (request_dma(dma, "esp serial")) {
-			free_pages((unsigned long)dma_buffer,
-				   get_order(DMA_BUFFER_SZ));
-			dma_buffer = NULL;
-			info->stat_flags |= ESP_STAT_USE_PIO;
-		}
-
-	}
-
-	info->MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
-
-	spin_lock_irqsave(&info->lock, flags);
-	serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
-	serial_out(info, UART_ESI_CMD2, UART_MCR);
-	serial_out(info, UART_ESI_CMD2, info->MCR);
-
-	/*
-	 * Finally, enable interrupts
-	 */
-	/* info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; */
-	info->IER = UART_IER_RLSI | UART_IER_RDI | UART_IER_DMA_TMOUT |
-			UART_IER_DMA_TC;
-	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
-	serial_out(info, UART_ESI_CMD2, info->IER);
-
-	if (info->port.tty)
-		clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	spin_unlock_irqrestore(&info->lock, flags);
-
-	/*
-	 * Set up the tty->alt_speed kludge
-	 */
-	if (info->port.tty) {
-		if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			info->port.tty->alt_speed = 57600;
-		if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			info->port.tty->alt_speed = 115200;
-		if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			info->port.tty->alt_speed = 230400;
-		if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			info->port.tty->alt_speed = 460800;
-	}
-
-	/*
-	 * set the speed of the serial port
-	 */
-	change_speed(info);
-	info->port.flags |= ASYNC_INITIALIZED;
-	return 0;
-
-out:
-	spin_unlock_irqrestore(&info->lock, flags);
-out_unlocked:
-	return retval;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void shutdown(struct esp_struct *info)
-{
-	unsigned long	flags, f;
-
-	if (!(info->port.flags & ASYNC_INITIALIZED))
-		return;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("Shutting down serial port %d (irq %d)....", info->line,
-	       info->irq);
-#endif
-
-	spin_lock_irqsave(&info->lock, flags);
-	/*
-	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
-	 * here so the queue might never be waken up
-	 */
-	wake_up_interruptible(&info->port.delta_msr_wait);
-	wake_up_interruptible(&info->break_wait);
-
-	/* stop a DMA transfer on the port being closed */
-	/* DMA lock is higher priority always */
-	if (info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) {
-		f = claim_dma_lock();
-		disable_dma(dma);
-		clear_dma_ff(dma);
-		release_dma_lock(f);
-
-		dma_bytes = 0;
-	}
-
-	/*
-	 * Free the IRQ
-	 */
-	free_irq(info->irq, info);
-
-	if (dma_buffer) {
-		struct esp_struct *current_port = ports;
-
-		while (current_port) {
-			if ((current_port != info) &&
-			    (current_port->port.flags & ASYNC_INITIALIZED))
-				break;
-
-			current_port = current_port->next_port;
-		}
-
-		if (!current_port) {
-			free_dma(dma);
-			free_pages((unsigned long)dma_buffer,
-				   get_order(DMA_BUFFER_SZ));
-			dma_buffer = NULL;
-		}
-	}
-
-	if (info->xmit_buf) {
-		free_page((unsigned long) info->xmit_buf);
-		info->xmit_buf = NULL;
-	}
-
-	info->IER = 0;
-	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
-	serial_out(info, UART_ESI_CMD2, 0x00);
-
-	if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL))
-		info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
-
-	info->MCR &= ~UART_MCR_OUT2;
-	serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
-	serial_out(info, UART_ESI_CMD2, UART_MCR);
-	serial_out(info, UART_ESI_CMD2, info->MCR);
-
-	if (info->port.tty)
-		set_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
-	info->port.flags &= ~ASYNC_INITIALIZED;
-	spin_unlock_irqrestore(&info->lock, flags);
-}
-
-/*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
-static void change_speed(struct esp_struct *info)
-{
-	unsigned short port;
-	int	quot = 0;
-	unsigned cflag, cval;
-	int	baud, bits;
-	unsigned char flow1 = 0, flow2 = 0;
-	unsigned long flags;
-
-	if (!info->port.tty || !info->port.tty->termios)
-		return;
-	cflag = info->port.tty->termios->c_cflag;
-	port = info->io_port;
-
-	/* byte size and parity */
-	switch (cflag & CSIZE) {
-	case CS5: cval = 0x00; bits = 7; break;
-	case CS6: cval = 0x01; bits = 8; break;
-	case CS7: cval = 0x02; bits = 9; break;
-	case CS8: cval = 0x03; bits = 10; break;
-	default:  cval = 0x00; bits = 7; break;
-	}
-	if (cflag & CSTOPB) {
-		cval |= 0x04;
-		bits++;
-	}
-	if (cflag & PARENB) {
-		cval |= UART_LCR_PARITY;
-		bits++;
-	}
-	if (!(cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-#ifdef CMSPAR
-	if (cflag & CMSPAR)
-		cval |= UART_LCR_SPAR;
-#endif
-	baud = tty_get_baud_rate(info->port.tty);
-	if (baud == 38400 &&
-		((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
-		quot = info->custom_divisor;
-	else {
-		if (baud == 134) /* Special case since 134 is really 134.5 */
-			quot = (2*BASE_BAUD / 269);
-		else if (baud)
-			quot = BASE_BAUD / baud;
-	}
-	/* If the quotient is ever zero, default to 9600 bps */
-	if (!quot)
-		quot = BASE_BAUD / 9600;
-
-	if (baud) {
-		/* Actual rate */
-		baud = BASE_BAUD/quot;
-		tty_encode_baud_rate(info->port.tty, baud, baud);
-	}
-	info->timeout = ((1024 * HZ * bits * quot) / BASE_BAUD) + (HZ / 50);
-
-	/* CTS flow control flag and modem status interrupts */
-	/* info->IER &= ~UART_IER_MSI; */
-	if (cflag & CRTSCTS) {
-		info->port.flags |= ASYNC_CTS_FLOW;
-		/* info->IER |= UART_IER_MSI; */
-		flow1 = 0x04;
-		flow2 = 0x10;
-	} else
-		info->port.flags &= ~ASYNC_CTS_FLOW;
-	if (cflag & CLOCAL)
-		info->port.flags &= ~ASYNC_CHECK_CD;
-	else
-		info->port.flags |= ASYNC_CHECK_CD;
-
-	/*
-	 * Set up parity check flag
-	 */
-	info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (I_INPCK(info->port.tty))
-		info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
-		info->read_status_mask |= UART_LSR_BI;
-
-	info->ignore_status_mask = 0;
-#if 0
-	/* This should be safe, but for some broken bits of hardware... */
-	if (I_IGNPAR(info->port.tty)) {
-		info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-		info->read_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	}
-#endif
-	if (I_IGNBRK(info->port.tty)) {
-		info->ignore_status_mask |= UART_LSR_BI;
-		info->read_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignore parity and break indicators, ignore
-		 * overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(info->port.tty)) {
-			info->ignore_status_mask |= UART_LSR_OE | \
-				UART_LSR_PE | UART_LSR_FE;
-			info->read_status_mask |= UART_LSR_OE | \
-				UART_LSR_PE | UART_LSR_FE;
-		}
-	}
-
-	if (I_IXOFF(info->port.tty))
-		flow1 |= 0x81;
-
-	spin_lock_irqsave(&info->lock, flags);
-	/* set baud */
-	serial_out(info, UART_ESI_CMD1, ESI_SET_BAUD);
-	serial_out(info, UART_ESI_CMD2, quot >> 8);
-	serial_out(info, UART_ESI_CMD2, quot & 0xff);
-
-	/* set data bits, parity, etc. */
-	serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
-	serial_out(info, UART_ESI_CMD2, UART_LCR);
-	serial_out(info, UART_ESI_CMD2, cval);
-
-	/* Enable flow control */
-	serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_CNTL);
-	serial_out(info, UART_ESI_CMD2, flow1);
-	serial_out(info, UART_ESI_CMD2, flow2);
-
-	/* set flow control characters (XON/XOFF only) */
-	if (I_IXOFF(info->port.tty)) {
-		serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_CHARS);
-		serial_out(info, UART_ESI_CMD2, START_CHAR(info->port.tty));
-		serial_out(info, UART_ESI_CMD2, STOP_CHAR(info->port.tty));
-		serial_out(info, UART_ESI_CMD2, 0x10);
-		serial_out(info, UART_ESI_CMD2, 0x21);
-		switch (cflag & CSIZE) {
-		case CS5:
-			serial_out(info, UART_ESI_CMD2, 0x1f);
-			break;
-		case CS6:
-			serial_out(info, UART_ESI_CMD2, 0x3f);
-			break;
-		case CS7:
-		case CS8:
-			serial_out(info, UART_ESI_CMD2, 0x7f);
-			break;
-		default:
-			serial_out(info, UART_ESI_CMD2, 0xff);
-			break;
-		}
-	}
-
-	/* Set high/low water */
-	serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_LVL);
-	serial_out(info, UART_ESI_CMD2, info->config.flow_off >> 8);
-	serial_out(info, UART_ESI_CMD2, info->config.flow_off);
-	serial_out(info, UART_ESI_CMD2, info->config.flow_on >> 8);
-	serial_out(info, UART_ESI_CMD2, info->config.flow_on);
-
-	spin_unlock_irqrestore(&info->lock, flags);
-}
-
-static int rs_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct esp_struct *info = tty->driver_data;
-	unsigned long flags;
-	int ret = 0;
-
-	if (serial_paranoia_check(info, tty->name, "rs_put_char"))
-		return 0;
-
-	if (!info->xmit_buf)
-		return 0;
-
-	spin_lock_irqsave(&info->lock, flags);
-	if (info->xmit_cnt < ESP_XMIT_SIZE - 1) {
-		info->xmit_buf[info->xmit_head++] = ch;
-		info->xmit_head &= ESP_XMIT_SIZE-1;
-		info->xmit_cnt++;
-		ret = 1;
-	}
-	spin_unlock_irqrestore(&info->lock, flags);
-	return ret;
-}
-
-static void rs_flush_chars(struct tty_struct *tty)
-{
-	struct esp_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_flush_chars"))
-		return;
-
-	spin_lock_irqsave(&info->lock, flags);
-
-	if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf)
-		goto out;
-
-	if (!(info->IER & UART_IER_THRI)) {
-		info->IER |= UART_IER_THRI;
-		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
-		serial_out(info, UART_ESI_CMD2, info->IER);
-	}
-out:
-	spin_unlock_irqrestore(&info->lock, flags);
-}
-
-static int rs_write(struct tty_struct *tty,
-		    const unsigned char *buf, int count)
-{
-	int	c, t, ret = 0;
-	struct esp_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_write"))
-		return 0;
-
-	if (!info->xmit_buf)
-		return 0;
-
-	while (1) {
-		/* Thanks to R. Wolff for suggesting how to do this with */
-		/* interrupts enabled */
-
-		c = count;
-		t = ESP_XMIT_SIZE - info->xmit_cnt - 1;
-
-		if (t < c)
-			c = t;
-
-		t = ESP_XMIT_SIZE - info->xmit_head;
-
-		if (t < c)
-			c = t;
-
-		if (c <= 0)
-			break;
-
-		memcpy(info->xmit_buf + info->xmit_head, buf, c);
-
-		info->xmit_head = (info->xmit_head + c) & (ESP_XMIT_SIZE-1);
-		info->xmit_cnt += c;
-		buf += c;
-		count -= c;
-		ret += c;
-	}
-
-	spin_lock_irqsave(&info->lock, flags);
-
-	if (info->xmit_cnt && !tty->stopped && !(info->IER & UART_IER_THRI)) {
-		info->IER |= UART_IER_THRI;
-		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
-		serial_out(info, UART_ESI_CMD2, info->IER);
-	}
-
-	spin_unlock_irqrestore(&info->lock, flags);
-	return ret;
-}
-
-static int rs_write_room(struct tty_struct *tty)
-{
-	struct esp_struct *info = tty->driver_data;
-	int	ret;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_write_room"))
-		return 0;
-
-	spin_lock_irqsave(&info->lock, flags);
-
-	ret = ESP_XMIT_SIZE - info->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-	spin_unlock_irqrestore(&info->lock, flags);
-	return ret;
-}
-
-static int rs_chars_in_buffer(struct tty_struct *tty)
-{
-	struct esp_struct *info = tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer"))
-		return 0;
-	return info->xmit_cnt;
-}
-
-static void rs_flush_buffer(struct tty_struct *tty)
-{
-	struct esp_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
-		return;
-	spin_lock_irqsave(&info->lock, flags);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	spin_unlock_irqrestore(&info->lock, flags);
-	tty_wakeup(tty);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_throttle()
- *
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void rs_throttle(struct tty_struct *tty)
-{
-	struct esp_struct *info = tty->driver_data;
-	unsigned long flags;
-#ifdef SERIAL_DEBUG_THROTTLE
-	char	buf[64];
-
-	printk("throttle %s: %d....\n", tty_name(tty, buf),
-						tty_chars_in_buffer(tty));
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "rs_throttle"))
-		return;
-
-	spin_lock_irqsave(&info->lock, flags);
-	info->IER &= ~UART_IER_RDI;
-	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
-	serial_out(info, UART_ESI_CMD2, info->IER);
-	serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);
-	serial_out(info, UART_ESI_CMD2, 0x00);
-	spin_unlock_irqrestore(&info->lock, flags);
-}
-
-static void rs_unthrottle(struct tty_struct *tty)
-{
-	struct esp_struct *info = tty->driver_data;
-	unsigned long flags;
-#ifdef SERIAL_DEBUG_THROTTLE
-	char	buf[64];
-
-	printk(KERN_DEBUG "unthrottle %s: %d....\n", tty_name(tty, buf),
-	       tty_chars_in_buffer(tty));
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "rs_unthrottle"))
-		return;
-
-	spin_lock_irqsave(&info->lock, flags);
-	info->IER |= UART_IER_RDI;
-	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
-	serial_out(info, UART_ESI_CMD2, info->IER);
-	serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);
-	serial_out(info, UART_ESI_CMD2, info->config.rx_timeout);
-	spin_unlock_irqrestore(&info->lock, flags);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-static int get_serial_info(struct esp_struct *info,
-			   struct serial_struct __user *retinfo)
-{
-	struct serial_struct tmp;
-
-	lock_kernel();
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.type = PORT_16550A;
-	tmp.line = info->line;
-	tmp.port = info->io_port;
-	tmp.irq = info->irq;
-	tmp.flags = info->port.flags;
-	tmp.xmit_fifo_size = 1024;
-	tmp.baud_base = BASE_BAUD;
-	tmp.close_delay = info->close_delay;
-	tmp.closing_wait = info->closing_wait;
-	tmp.custom_divisor = info->custom_divisor;
-	tmp.hub6 = 0;
-	unlock_kernel();
-	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-		return -EFAULT;
-	return 0;
-}
-
-static int get_esp_config(struct esp_struct *info,
-			  struct hayes_esp_config __user *retinfo)
-{
-	struct hayes_esp_config tmp;
-
-	if (!retinfo)
-		return -EFAULT;
-
-	memset(&tmp, 0, sizeof(tmp));
-	lock_kernel();
-	tmp.rx_timeout = info->config.rx_timeout;
-	tmp.rx_trigger = info->config.rx_trigger;
-	tmp.tx_trigger = info->config.tx_trigger;
-	tmp.flow_off = info->config.flow_off;
-	tmp.flow_on = info->config.flow_on;
-	tmp.pio_threshold = info->config.pio_threshold;
-	tmp.dma_channel = (info->stat_flags & ESP_STAT_NEVER_DMA ? 0 : dma);
-	unlock_kernel();
-
-	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
-}
-
-static int set_serial_info(struct esp_struct *info,
-			   struct serial_struct __user *new_info)
-{
-	struct serial_struct new_serial;
-	struct esp_struct old_info;
-	unsigned int change_irq;
-	int retval = 0;
-	struct esp_struct *current_async;
-
-	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
-		return -EFAULT;
-	old_info = *info;
-
-	if ((new_serial.type != PORT_16550A) ||
-	    (new_serial.hub6) ||
-	    (info->io_port != new_serial.port) ||
-	    (new_serial.baud_base != BASE_BAUD) ||
-	    (new_serial.irq > 15) ||
-	    (new_serial.irq < 2) ||
-	    (new_serial.irq == 6) ||
-	    (new_serial.irq == 8) ||
-	    (new_serial.irq == 13))
-		return -EINVAL;
-
-	change_irq = new_serial.irq != info->irq;
-
-	if (change_irq && (info->line % 8))
-		return -EINVAL;
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if (change_irq ||
-		    (new_serial.close_delay != info->close_delay) ||
-		    ((new_serial.flags & ~ASYNC_USR_MASK) !=
-		     (info->port.flags & ~ASYNC_USR_MASK)))
-			return -EPERM;
-		info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) |
-			       (new_serial.flags & ASYNC_USR_MASK));
-		info->custom_divisor = new_serial.custom_divisor;
-	} else {
-		if (new_serial.irq == 2)
-			new_serial.irq = 9;
-
-		if (change_irq) {
-			current_async = ports;
-
-			while (current_async) {
-				if ((current_async->line >= info->line) &&
-				    (current_async->line < (info->line + 8))) {
-					if (current_async == info) {
-						if (current_async->port.count > 1)
-							return -EBUSY;
-					} else if (current_async->port.count)
-						return -EBUSY;
-				}
-
-				current_async = current_async->next_port;
-			}
-		}
-
-		/*
-		 * OK, past this point, all the error checking has been done.
-		 * At this point, we start making changes.....
-		 */
-
-		info->port.flags = ((info->port.flags & ~ASYNC_FLAGS) |
-			       (new_serial.flags & ASYNC_FLAGS));
-		info->custom_divisor = new_serial.custom_divisor;
-		info->close_delay = new_serial.close_delay * HZ/100;
-		info->closing_wait = new_serial.closing_wait * HZ/100;
-
-		if (change_irq) {
-			/*
-			 * We need to shutdown the serial port at the old
-			 * port/irq combination.
-			 */
-			shutdown(info);
-
-			current_async = ports;
-
-			while (current_async) {
-				if ((current_async->line >= info->line) &&
-				    (current_async->line < (info->line + 8)))
-					current_async->irq = new_serial.irq;
-
-				current_async = current_async->next_port;
-			}
-
-			serial_out(info, UART_ESI_CMD1, ESI_SET_ENH_IRQ);
-			if (info->irq == 9)
-				serial_out(info, UART_ESI_CMD2, 0x02);
-			else
-				serial_out(info, UART_ESI_CMD2, info->irq);
-		}
-	}
-
-	if (info->port.flags & ASYNC_INITIALIZED) {
-		if (((old_info.port.flags & ASYNC_SPD_MASK) !=
-		     (info->port.flags & ASYNC_SPD_MASK)) ||
-		    (old_info.custom_divisor != info->custom_divisor)) {
-			if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-				info->port.tty->alt_speed = 57600;
-			if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-				info->port.tty->alt_speed = 115200;
-			if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-				info->port.tty->alt_speed = 230400;
-			if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-				info->port.tty->alt_speed = 460800;
-			change_speed(info);
-		}
-	} else
-		retval = startup(info);
-
-	return retval;
-}
-
-static int set_esp_config(struct esp_struct *info,
-			  struct hayes_esp_config __user *new_info)
-{
-	struct hayes_esp_config new_config;
-	unsigned int change_dma;
-	int retval = 0;
-	struct esp_struct *current_async;
-	unsigned long flags;
-
-	/* Perhaps a non-sysadmin user should be able to do some of these */
-	/* operations.  I haven't decided yet. */
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
-	if (copy_from_user(&new_config, new_info, sizeof(new_config)))
-		return -EFAULT;
-
-	if ((new_config.flow_on >= new_config.flow_off) ||
-	    (new_config.rx_trigger < 1) ||
-	    (new_config.tx_trigger < 1) ||
-	    (new_config.flow_off < 1) ||
-	    (new_config.flow_on < 1) ||
-	    (new_config.rx_trigger > 1023) ||
-	    (new_config.tx_trigger > 1023) ||
-	    (new_config.flow_off > 1023) ||
-	    (new_config.flow_on > 1023) ||
-	    (new_config.pio_threshold < 0) ||
-	    (new_config.pio_threshold > 1024))
-		return -EINVAL;
-
-	if ((new_config.dma_channel != 1) && (new_config.dma_channel != 3))
-		new_config.dma_channel = 0;
-
-	if (info->stat_flags & ESP_STAT_NEVER_DMA)
-		change_dma = new_config.dma_channel;
-	else
-		change_dma = (new_config.dma_channel != dma);
-
-	if (change_dma) {
-		if (new_config.dma_channel) {
-			/* PIO mode to DMA mode transition OR */
-			/* change current DMA channel */
-			current_async = ports;
-
-			while (current_async) {
-				if (current_async == info) {
-					if (current_async->port.count > 1)
-						return -EBUSY;
-				} else if (current_async->port.count)
-					return -EBUSY;
-
-				current_async = current_async->next_port;
-			}
-
-			shutdown(info);
-			dma = new_config.dma_channel;
-			info->stat_flags &= ~ESP_STAT_NEVER_DMA;
-
-			/* all ports must use the same DMA channel */
-
-			spin_lock_irqsave(&info->lock, flags);
-			current_async = ports;
-
-			while (current_async) {
-				esp_basic_init(current_async);
-				current_async = current_async->next_port;
-			}
-			spin_unlock_irqrestore(&info->lock, flags);
-		} else {
-			/* DMA mode to PIO mode only */
-			if (info->port.count > 1)
-				return -EBUSY;
-
-			shutdown(info);
-			spin_lock_irqsave(&info->lock, flags);
-			info->stat_flags |= ESP_STAT_NEVER_DMA;
-			esp_basic_init(info);
-			spin_unlock_irqrestore(&info->lock, flags);
-		}
-	}
-
-	info->config.pio_threshold = new_config.pio_threshold;
-
-	if ((new_config.flow_off != info->config.flow_off) ||
-	    (new_config.flow_on != info->config.flow_on)) {
-		info->config.flow_off = new_config.flow_off;
-		info->config.flow_on = new_config.flow_on;
-
-		spin_lock_irqsave(&info->lock, flags);
-		serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_LVL);
-		serial_out(info, UART_ESI_CMD2, new_config.flow_off >> 8);
-		serial_out(info, UART_ESI_CMD2, new_config.flow_off);
-		serial_out(info, UART_ESI_CMD2, new_config.flow_on >> 8);
-		serial_out(info, UART_ESI_CMD2, new_config.flow_on);
-		spin_unlock_irqrestore(&info->lock, flags);
-	}
-
-	if ((new_config.rx_trigger != info->config.rx_trigger) ||
-	    (new_config.tx_trigger != info->config.tx_trigger)) {
-		info->config.rx_trigger = new_config.rx_trigger;
-		info->config.tx_trigger = new_config.tx_trigger;
-		spin_lock_irqsave(&info->lock, flags);
-		serial_out(info, UART_ESI_CMD1, ESI_SET_TRIGGER);
-		serial_out(info, UART_ESI_CMD2,
-			   new_config.rx_trigger >> 8);
-		serial_out(info, UART_ESI_CMD2, new_config.rx_trigger);
-		serial_out(info, UART_ESI_CMD2,
-			   new_config.tx_trigger >> 8);
-		serial_out(info, UART_ESI_CMD2, new_config.tx_trigger);
-		spin_unlock_irqrestore(&info->lock, flags);
-	}
-
-	if (new_config.rx_timeout != info->config.rx_timeout) {
-		info->config.rx_timeout = new_config.rx_timeout;
-		spin_lock_irqsave(&info->lock, flags);
-
-		if (info->IER & UART_IER_RDI) {
-			serial_out(info, UART_ESI_CMD1,
-				   ESI_SET_RX_TIMEOUT);
-			serial_out(info, UART_ESI_CMD2,
-				   new_config.rx_timeout);
-		}
-
-		spin_unlock_irqrestore(&info->lock, flags);
-	}
-
-	if (!(info->port.flags & ASYNC_INITIALIZED))
-		retval = startup(info);
-
-	return retval;
-}
-
-/*
- * get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- * 	    is emptied.  On bus types like RS485, the transmitter must
- * 	    release the bus after transmitting. This must be done when
- * 	    the transmit shift register is empty, not be done when the
- * 	    transmit holding register is empty.  This functionality
- * 	    allows an RS485 driver to be written in user space.
- */
-static int get_lsr_info(struct esp_struct *info, unsigned int __user *value)
-{
-	unsigned char status;
-	unsigned int result;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock, flags);
-	serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
-	status = serial_in(info, UART_ESI_STAT1);
-	spin_unlock_irqrestore(&info->lock, flags);
-	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
-	return put_user(result, value);
-}
-
-
-static int esp_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct esp_struct *info = tty->driver_data;
-	unsigned char control, status;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, __func__))
-		return -ENODEV;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	control = info->MCR;
-
-	spin_lock_irqsave(&info->lock, flags);
-	serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
-	status = serial_in(info, UART_ESI_STAT2);
-	spin_unlock_irqrestore(&info->lock, flags);
-
-	return    ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
-		| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
-		| ((status  & UART_MSR_DCD) ? TIOCM_CAR : 0)
-		| ((status  & UART_MSR_RI) ? TIOCM_RNG : 0)
-		| ((status  & UART_MSR_DSR) ? TIOCM_DSR : 0)
-		| ((status  & UART_MSR_CTS) ? TIOCM_CTS : 0);
-}
-
-static int esp_tiocmset(struct tty_struct *tty, struct file *file,
-			unsigned int set, unsigned int clear)
-{
-	struct esp_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, __func__))
-		return -ENODEV;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	spin_lock_irqsave(&info->lock, flags);
-
-	if (set & TIOCM_RTS)
-		info->MCR |= UART_MCR_RTS;
-	if (set & TIOCM_DTR)
-		info->MCR |= UART_MCR_DTR;
-
-	if (clear & TIOCM_RTS)
-		info->MCR &= ~UART_MCR_RTS;
-	if (clear & TIOCM_DTR)
-		info->MCR &= ~UART_MCR_DTR;
-
-	serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
-	serial_out(info, UART_ESI_CMD2, UART_MCR);
-	serial_out(info, UART_ESI_CMD2, info->MCR);
-
-	spin_unlock_irqrestore(&info->lock, flags);
-	return 0;
-}
-
-/*
- * rs_break() --- routine which turns the break handling on or off
- */
-static int esp_break(struct tty_struct *tty, int break_state)
-{
-	struct esp_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "esp_break"))
-		return -EINVAL;
-
-	if (break_state == -1) {
-		spin_lock_irqsave(&info->lock, flags);
-		serial_out(info, UART_ESI_CMD1, ESI_ISSUE_BREAK);
-		serial_out(info, UART_ESI_CMD2, 0x01);
-		spin_unlock_irqrestore(&info->lock, flags);
-
-		/* FIXME - new style wait needed here */
-		interruptible_sleep_on(&info->break_wait);
-	} else {
-		spin_lock_irqsave(&info->lock, flags);
-		serial_out(info, UART_ESI_CMD1, ESI_ISSUE_BREAK);
-		serial_out(info, UART_ESI_CMD2, 0x00);
-		spin_unlock_irqrestore(&info->lock, flags);
-	}
-	return 0;
-}
-
-static int rs_ioctl(struct tty_struct *tty, struct file *file,
-		    unsigned int cmd, unsigned long arg)
-{
-	struct esp_struct *info = tty->driver_data;
-	struct async_icount cprev, cnow;	/* kernel counter temps */
-	struct serial_icounter_struct __user *p_cuser;	/* user space */
-	void __user *argp = (void __user *)arg;
-	unsigned long flags;
-	int ret;
-
-	if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
-		return -ENODEV;
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&
-	    (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT) &&
-	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT) &&
-	    (cmd != TIOCGHAYESESP) && (cmd != TIOCSHAYESESP)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
-		    return -EIO;
-	}
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		return get_serial_info(info, argp);
-	case TIOCSSERIAL:
-		lock_kernel();
-		ret = set_serial_info(info, argp);
-		unlock_kernel();
-		return ret;
-	case TIOCSERGWILD:
-		return put_user(0L, (unsigned long __user *)argp);
-	case TIOCSERGETLSR: /* Get line status register */
-		return get_lsr_info(info, argp);
-	case TIOCSERSWILD:
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-		return 0;
-	/*
-	 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-	 * - mask passed in arg for lines of interest
-	 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-	 * Caller should use TIOCGICOUNT to see which one it was
-	 */
-	case TIOCMIWAIT:
-		spin_lock_irqsave(&info->lock, flags);
-		cprev = info->icount;	/* note the counters on entry */
-		spin_unlock_irqrestore(&info->lock, flags);
-		while (1) {
-			/* FIXME: convert to new style wakeup */
-			interruptible_sleep_on(&info->port.delta_msr_wait);
-			/* see if a signal did it */
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-			spin_lock_irqsave(&info->lock, flags);
-			cnow = info->icount;	/* atomic copy */
-			spin_unlock_irqrestore(&info->lock, flags);
-			if (cnow.rng == cprev.rng &&
-			    cnow.dsr == cprev.dsr &&
-			    cnow.dcd == cprev.dcd &&
-			    cnow.cts == cprev.cts)
-				return -EIO; /* no change => error */
-			if (((arg & TIOCM_RNG) &&
-			     (cnow.rng != cprev.rng)) ||
-			     ((arg & TIOCM_DSR) &&
-			      (cnow.dsr != cprev.dsr)) ||
-			     ((arg & TIOCM_CD) &&
-			      (cnow.dcd != cprev.dcd)) ||
-			     ((arg & TIOCM_CTS) &&
-			      (cnow.cts != cprev.cts))) {
-				return 0;
-			}
-			cprev = cnow;
-		}
-		/* NOTREACHED */
-	/*
-	 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-	 * Return: write counters to the user passed counter struct
-	 * NB: both 1->0 and 0->1 transitions are counted except for
-	 *     RI where only 0->1 is counted.
-	 */
-	case TIOCGICOUNT:
-		spin_lock_irqsave(&info->lock, flags);
-		cnow = info->icount;
-		spin_unlock_irqrestore(&info->lock, flags);
-		p_cuser = argp;
-		if (put_user(cnow.cts, &p_cuser->cts) ||
-		    put_user(cnow.dsr, &p_cuser->dsr) ||
-		    put_user(cnow.rng, &p_cuser->rng) ||
-		    put_user(cnow.dcd, &p_cuser->dcd))
-			return -EFAULT;
-			return 0;
-	case TIOCGHAYESESP:
-		return get_esp_config(info, argp);
-	case TIOCSHAYESESP:
-		lock_kernel();
-		ret = set_esp_config(info, argp);
-		unlock_kernel();
-		return ret;
-	default:
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct esp_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	change_speed(info);
-
-	spin_lock_irqsave(&info->lock, flags);
-
-	/* Handle transition to B0 status */
-	if ((old_termios->c_cflag & CBAUD) &&
-		!(tty->termios->c_cflag & CBAUD)) {
-		info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
-		serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
-		serial_out(info, UART_ESI_CMD2, UART_MCR);
-		serial_out(info, UART_ESI_CMD2, info->MCR);
-	}
-
-	/* Handle transition away from B0 status */
-	if (!(old_termios->c_cflag & CBAUD) &&
-		(tty->termios->c_cflag & CBAUD)) {
-		info->MCR |= (UART_MCR_DTR | UART_MCR_RTS);
-		serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
-		serial_out(info, UART_ESI_CMD2, UART_MCR);
-		serial_out(info, UART_ESI_CMD2, info->MCR);
-	}
-
-	spin_unlock_irqrestore(&info->lock, flags);
-
-	/* Handle turning of CRTSCTS */
-	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		rs_start(tty);
-	}
-}
-
-/*
- * ------------------------------------------------------------
- * rs_close()
- *
- * This routine is called when the serial port gets closed.  First, we
- * wait for the last remaining data to be sent.  Then, we unlink its
- * async structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- * ------------------------------------------------------------
- */
-static void rs_close(struct tty_struct *tty, struct file *filp)
-{
-	struct esp_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
-		return;
-
-	spin_lock_irqsave(&info->lock, flags);
-
-	if (tty_hung_up_p(filp)) {
-		DBG_CNT("before DEC-hung");
-		goto out;
-	}
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk(KERN_DEBUG "rs_close ttys%d, count = %d\n",
-						info->line, info->port.count);
-#endif
-	if (tty->count == 1 && info->port.count != 1) {
-		/*
-		 * Uh, oh.  tty->count is 1, which means that the tty
-		 * structure will be freed.  Info->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.
-		 */
-		printk(KERN_DEBUG "rs_close: bad serial port count; tty->count is 1, info->port.count is %d\n", info->port.count);
-		info->port.count = 1;
-	}
-	if (--info->port.count < 0) {
-		printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n",
-		       info->line, info->port.count);
-		info->port.count = 0;
-	}
-	if (info->port.count) {
-		DBG_CNT("before DEC-2");
-		goto out;
-	}
-	info->port.flags |= ASYNC_CLOSING;
-
-	spin_unlock_irqrestore(&info->lock, 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 (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-		tty_wait_until_sent(tty, info->closing_wait);
-	/*
-	 * At this point we stop accepting input.  To do this, we
-	 * disable the receive line status interrupts, and tell the
-	 * interrupt driver to stop checking the data ready bit in the
-	 * line status register.
-	 */
-	/* info->IER &= ~UART_IER_RLSI; */
-	info->IER &= ~UART_IER_RDI;
-	info->read_status_mask &= ~UART_LSR_DR;
-	if (info->port.flags & ASYNC_INITIALIZED) {
-
-		spin_lock_irqsave(&info->lock, flags);
-		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
-		serial_out(info, UART_ESI_CMD2, info->IER);
-
-		/* disable receive timeout */
-		serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);
-		serial_out(info, UART_ESI_CMD2, 0x00);
-
-		spin_unlock_irqrestore(&info->lock, flags);
-
-		/*
-		 * Before we drop DTR, make sure the UART transmitter
-		 * has completely drained; this is especially
-		 * important if there is a transmit FIFO!
-		 */
-		rs_wait_until_sent(tty, info->timeout);
-	}
-	shutdown(info);
-	rs_flush_buffer(tty);
-	tty_ldisc_flush(tty);
-	tty->closing = 0;
-	info->port.tty = NULL;
-
-	if (info->port.blocked_open) {
-		if (info->close_delay)
-			msleep_interruptible(jiffies_to_msecs(info->close_delay));
-		wake_up_interruptible(&info->port.open_wait);
-	}
-	info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-	wake_up_interruptible(&info->port.close_wait);
-	return;
-
-out:
-	spin_unlock_irqrestore(&info->lock, flags);
-}
-
-static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct esp_struct *info = tty->driver_data;
-	unsigned long orig_jiffies, char_time;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent"))
-		return;
-
-	orig_jiffies = jiffies;
-	char_time = ((info->timeout - HZ / 50) / 1024) / 5;
-
-	if (!char_time)
-		char_time = 1;
-
-	spin_lock_irqsave(&info->lock, flags);
-	serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
-	serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
-
-	while ((serial_in(info, UART_ESI_STAT1) != 0x03) ||
-		(serial_in(info, UART_ESI_STAT2) != 0xff)) {
-
-		spin_unlock_irqrestore(&info->lock, flags);
-		msleep_interruptible(jiffies_to_msecs(char_time));
-
-		if (signal_pending(current))
-			return;
-
-		if (timeout && time_after(jiffies, orig_jiffies + timeout))
-			return;
-
-		spin_lock_irqsave(&info->lock, flags);
-		serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
-		serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
-	}
-	spin_unlock_irqrestore(&info->lock, flags);
-	set_current_state(TASK_RUNNING);
-}
-
-/*
- * esp_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void esp_hangup(struct tty_struct *tty)
-{
-	struct esp_struct *info = tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->name, "esp_hangup"))
-		return;
-
-	rs_flush_buffer(tty);
-	shutdown(info);
-	info->port.count = 0;
-	info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-	info->port.tty = NULL;
-	wake_up_interruptible(&info->port.open_wait);
-}
-
-static int esp_carrier_raised(struct tty_port *port)
-{
-	struct esp_struct *info = container_of(port, struct esp_struct, port);
-	serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
-	if (serial_in(info, UART_ESI_STAT2) & UART_MSR_DCD)
-		return 1;
-	return 0;
-}
-
-/*
- * ------------------------------------------------------------
- * esp_open() and friends
- * ------------------------------------------------------------
- */
-static int block_til_ready(struct tty_struct *tty, struct file *filp,
-			   struct esp_struct *info)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	int		retval;
-	int		do_clocal = 0;
-	unsigned long	flags;
-	int		cd;
-	struct tty_port *port = &info->port;
-
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * until it's done, and then try again.
-	 */
-	if (tty_hung_up_p(filp) ||
-	    (port->flags & ASYNC_CLOSING)) {
-		if (port->flags & ASYNC_CLOSING)
-			interruptible_sleep_on(&port->close_wait);
-#ifdef SERIAL_DO_RESTART
-		if (port->flags & ASYNC_HUP_NOTIFY)
-			return -EAGAIN;
-		else
-			return -ERESTARTSYS;
-#else
-		return -EAGAIN;
-#endif
-	}
-
-	/*
-	 * 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))) {
-		port->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	if (tty->termios->c_cflag & CLOCAL)
-		do_clocal = 1;
-
-	/*
-	 * Block waiting for the carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, port->count is dropped by one, so that
-	 * rs_close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-	retval = 0;
-	add_wait_queue(&port->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
-	printk(KERN_DEBUG "block_til_ready before block: ttys%d, count = %d\n",
-	       info->line, port->count);
-#endif
-	spin_lock_irqsave(&info->lock, flags);
-	if (!tty_hung_up_p(filp))
-		port->count--;
-	port->blocked_open++;
-	while (1) {
-		if ((tty->termios->c_cflag & CBAUD)) {
-			unsigned int scratch;
-
-			serial_out(info, UART_ESI_CMD1, ESI_READ_UART);
-			serial_out(info, UART_ESI_CMD2, UART_MCR);
-			scratch = serial_in(info, UART_ESI_STAT1);
-			serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
-			serial_out(info, UART_ESI_CMD2, UART_MCR);
-			serial_out(info, UART_ESI_CMD2,
-				scratch | UART_MCR_DTR | UART_MCR_RTS);
-		}
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp) ||
-		    !(port->flags & ASYNC_INITIALIZED)) {
-#ifdef SERIAL_DO_RESTART
-			if (port->flags & ASYNC_HUP_NOTIFY)
-				retval = -EAGAIN;
-			else
-				retval = -ERESTARTSYS;
-#else
-			retval = -EAGAIN;
-#endif
-			break;
-		}
-
-		cd = tty_port_carrier_raised(port);
-
-		if (!(port->flags & ASYNC_CLOSING) &&
-		    (do_clocal))
-			break;
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-#ifdef SERIAL_DEBUG_OPEN
-		printk(KERN_DEBUG "block_til_ready blocking: ttys%d, count = %d\n",
-		       info->line, port->count);
-#endif
-		spin_unlock_irqrestore(&info->lock, flags);
-		schedule();
-		spin_lock_irqsave(&info->lock, flags);
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&port->open_wait, &wait);
-	if (!tty_hung_up_p(filp))
-		port->count++;
-	port->blocked_open--;
-	spin_unlock_irqrestore(&info->lock, flags);
-#ifdef SERIAL_DEBUG_OPEN
-	printk(KERN_DEBUG "block_til_ready after blocking: ttys%d, count = %d\n",
-	       info->line, port->count);
-#endif
-	if (retval)
-		return retval;
-	port->flags |= ASYNC_NORMAL_ACTIVE;
-	return 0;
-}
-
-/*
- * This routine is called whenever a serial port is opened.  It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain.   It also performs the serial-specific
- * initialization for the tty structure.
- */
-static int esp_open(struct tty_struct *tty, struct file *filp)
-{
-	struct esp_struct	*info;
-	int 			retval, line;
-	unsigned long		flags;
-
-	line = tty->index;
-	if ((line < 0) || (line >= NR_PORTS))
-		return -ENODEV;
-
-	/* find the port in the chain */
-
-	info = ports;
-
-	while (info && (info->line != line))
-		info = info->next_port;
-
-	if (!info) {
-		serial_paranoia_check(info, tty->name, "esp_open");
-		return -ENODEV;
-	}
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk(KERN_DEBUG "esp_open %s, count = %d\n", tty->name, info->port.count);
-#endif
-	spin_lock_irqsave(&info->lock, flags);
-	info->port.count++;
-	tty->driver_data = info;
-	info->port.tty = tty;
-
-	spin_unlock_irqrestore(&info->lock, flags);
-
-	/*
-	 * Start up serial port
-	 */
-	retval = startup(info);
-	if (retval)
-		return retval;
-
-	retval = block_til_ready(tty, filp, info);
-	if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
-		printk(KERN_DEBUG "esp_open returning after block_til_ready with %d\n",
-		       retval);
-#endif
-		return retval;
-	}
-#ifdef SERIAL_DEBUG_OPEN
-	printk(KERN_DEBUG "esp_open %s successful...", tty->name);
-#endif
-	return 0;
-}
-
-/*
- * ---------------------------------------------------------------------
- * espserial_init() and friends
- *
- * espserial_init() is called at boot-time to initialize the serial driver.
- * ---------------------------------------------------------------------
- */
-
-/*
- * This routine prints out the appropriate serial driver version
- * number, and identifies which options were configured into this
- * driver.
- */
-
-static void __init show_serial_version(void)
-{
-	printk(KERN_INFO "%s version %s (DMA %u)\n",
-		serial_name, serial_version, dma);
-}
-
-/*
- * This routine is called by espserial_init() to initialize a specific serial
- * port.
- */
-static int autoconfig(struct esp_struct *info)
-{
-	int port_detected = 0;
-	unsigned long flags;
-
-	if (!request_region(info->io_port, REGION_SIZE, "esp serial"))
-		return -EIO;
-
-	spin_lock_irqsave(&info->lock, flags);
-	/*
-	 * Check for ESP card
-	 */
-
-	if (serial_in(info, UART_ESI_BASE) == 0xf3) {
-		serial_out(info, UART_ESI_CMD1, 0x00);
-		serial_out(info, UART_ESI_CMD1, 0x01);
-
-		if ((serial_in(info, UART_ESI_STAT2) & 0x70) == 0x20) {
-			port_detected = 1;
-
-			if (!(info->irq)) {
-				serial_out(info, UART_ESI_CMD1, 0x02);
-
-				if (serial_in(info, UART_ESI_STAT1) & 0x01)
-					info->irq = 3;
-				else
-					info->irq = 4;
-			}
-
-
-			/* put card in enhanced mode */
-			/* this prevents access through */
-			/* the "old" IO ports */
-			esp_basic_init(info);
-
-			/* clear out MCR */
-			serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
-			serial_out(info, UART_ESI_CMD2, UART_MCR);
-			serial_out(info, UART_ESI_CMD2, 0x00);
-		}
-	}
-	if (!port_detected)
-		release_region(info->io_port, REGION_SIZE);
-
-	spin_unlock_irqrestore(&info->lock, flags);
-	return (port_detected);
-}
-
-static const struct tty_operations esp_ops = {
-	.open = esp_open,
-	.close = rs_close,
-	.write = rs_write,
-	.put_char = rs_put_char,
-	.flush_chars = rs_flush_chars,
-	.write_room = rs_write_room,
-	.chars_in_buffer = rs_chars_in_buffer,
-	.flush_buffer = rs_flush_buffer,
-	.ioctl = rs_ioctl,
-	.throttle = rs_throttle,
-	.unthrottle = rs_unthrottle,
-	.set_termios = rs_set_termios,
-	.stop = rs_stop,
-	.start = rs_start,
-	.hangup = esp_hangup,
-	.break_ctl = esp_break,
-	.wait_until_sent = rs_wait_until_sent,
-	.tiocmget = esp_tiocmget,
-	.tiocmset = esp_tiocmset,
-};
-
-static const struct tty_port_operations esp_port_ops = {
-	.esp_carrier_raised,
-};
-
-/*
- * The serial driver boot-time initialization code!
- */
-static int __init espserial_init(void)
-{
-	int i, offset;
-	struct esp_struct *info;
-	struct esp_struct *last_primary = NULL;
-	int esp[] = { 0x100, 0x140, 0x180, 0x200, 0x240, 0x280, 0x300, 0x380 };
-
-	esp_driver = alloc_tty_driver(NR_PORTS);
-	if (!esp_driver)
-		return -ENOMEM;
-
-	for (i = 0; i < NR_PRIMARY; i++) {
-		if (irq[i] != 0) {
-			if ((irq[i] < 2) || (irq[i] > 15) || (irq[i] == 6) ||
-			    (irq[i] == 8) || (irq[i] == 13))
-				irq[i] = 0;
-			else if (irq[i] == 2)
-				irq[i] = 9;
-		}
-	}
-
-	if ((dma != 1) && (dma != 3))
-		dma = 0;
-
-	if ((rx_trigger < 1) || (rx_trigger > 1023))
-		rx_trigger = 768;
-
-	if ((tx_trigger < 1) || (tx_trigger > 1023))
-		tx_trigger = 768;
-
-	if ((flow_off < 1) || (flow_off > 1023))
-		flow_off = 1016;
-
-	if ((flow_on < 1) || (flow_on > 1023))
-		flow_on = 944;
-
-	if ((rx_timeout < 0) || (rx_timeout > 255))
-		rx_timeout = 128;
-
-	if (flow_on >= flow_off)
-		flow_on = flow_off - 1;
-
-	show_serial_version();
-
-	/* Initialize the tty_driver structure */
-
-	esp_driver->owner = THIS_MODULE;
-	esp_driver->name = "ttyP";
-	esp_driver->major = ESP_IN_MAJOR;
-	esp_driver->minor_start = 0;
-	esp_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	esp_driver->subtype = SERIAL_TYPE_NORMAL;
-	esp_driver->init_termios = tty_std_termios;
-	esp_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	esp_driver->init_termios.c_ispeed = 9600;
-	esp_driver->init_termios.c_ospeed = 9600;
-	esp_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(esp_driver, &esp_ops);
-	if (tty_register_driver(esp_driver)) {
-		printk(KERN_ERR "Couldn't register esp serial driver");
-		put_tty_driver(esp_driver);
-		return 1;
-	}
-
-	info = kzalloc(sizeof(struct esp_struct), GFP_KERNEL);
-
-	if (!info) {
-		printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n");
-		tty_unregister_driver(esp_driver);
-		put_tty_driver(esp_driver);
-		return 1;
-	}
-
-	spin_lock_init(&info->lock);
-	/* rx_trigger, tx_trigger are needed by autoconfig */
-	info->config.rx_trigger = rx_trigger;
-	info->config.tx_trigger = tx_trigger;
-
-	i = 0;
-	offset = 0;
-
-	do {
-		tty_port_init(&info->port);
-		info->port.ops = &esp_port_ops;
-		info->io_port = esp[i] + offset;
-		info->irq = irq[i];
-		info->line = (i * 8) + (offset / 8);
-
-		if (!autoconfig(info)) {
-			i++;
-			offset = 0;
-			continue;
-		}
-
-		info->custom_divisor = (divisor[i] >> (offset / 2)) & 0xf;
-		info->port.flags = STD_COM_FLAGS;
-		if (info->custom_divisor)
-			info->port.flags |= ASYNC_SPD_CUST;
-		info->magic = ESP_MAGIC;
-		info->close_delay = 5*HZ/10;
-		info->closing_wait = 30*HZ;
-		info->config.rx_timeout = rx_timeout;
-		info->config.flow_on = flow_on;
-		info->config.flow_off = flow_off;
-		info->config.pio_threshold = pio_threshold;
-		info->next_port = ports;
-		init_waitqueue_head(&info->break_wait);
-		ports = info;
-		printk(KERN_INFO "ttyP%d at 0x%04x (irq = %d) is an ESP ",
-			info->line, info->io_port, info->irq);
-
-		if (info->line % 8) {
-			printk("secondary port\n");
-			/* 8 port cards can't do DMA */
-			info->stat_flags |= ESP_STAT_NEVER_DMA;
-
-			if (last_primary)
-				last_primary->stat_flags |= ESP_STAT_NEVER_DMA;
-		} else {
-			printk("primary port\n");
-			last_primary = info;
-			irq[i] = info->irq;
-		}
-
-		if (!dma)
-			info->stat_flags |= ESP_STAT_NEVER_DMA;
-
-		info = kzalloc(sizeof(struct esp_struct), GFP_KERNEL);
-		if (!info) {
-			printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n");
-			/* allow use of the already detected ports */
-			return 0;
-		}
-
-		spin_lock_init(&info->lock);
-		/* rx_trigger, tx_trigger are needed by autoconfig */
-		info->config.rx_trigger = rx_trigger;
-		info->config.tx_trigger = tx_trigger;
-
-		if (offset == 56) {
-			i++;
-			offset = 0;
-		} else {
-			offset += 8;
-		}
-	} while (i < NR_PRIMARY);
-
-	/* free the last port memory allocation */
-	kfree(info);
-
-	return 0;
-}
-
-static void __exit espserial_exit(void)
-{
-	int e1;
-	struct esp_struct *temp_async;
-	struct esp_pio_buffer *pio_buf;
-
-	e1 = tty_unregister_driver(esp_driver);
-	if (e1)
-		printk(KERN_ERR "esp: failed to unregister driver (%d)\n", e1);
-	put_tty_driver(esp_driver);
-
-	while (ports) {
-		if (ports->io_port)
-			release_region(ports->io_port, REGION_SIZE);
-		temp_async = ports->next_port;
-		kfree(ports);
-		ports = temp_async;
-	}
-
-	if (dma_buffer)
-		free_pages((unsigned long)dma_buffer,
-			get_order(DMA_BUFFER_SZ));
-
-	while (free_pio_buf) {
-		pio_buf = free_pio_buf->next;
-		kfree(free_pio_buf);
-		free_pio_buf = pio_buf;
-	}
-}
-
-module_init(espserial_init);
-module_exit(espserial_exit);
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 426bfdd7f3e0..300d5bd6cd06 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -793,35 +793,30 @@ static inline void isicom_setup_board(struct isi_board *bp)
 {
 	int channel;
 	struct isi_port *port;
-	unsigned long flags;
 
-	spin_lock_irqsave(&bp->card_lock, flags);
-	if (bp->status & BOARD_ACTIVE) {
-		spin_unlock_irqrestore(&bp->card_lock, flags);
-		return;
+	bp->count++;
+	if (!(bp->status & BOARD_INIT)) {
+		port = bp->ports;
+		for (channel = 0; channel < bp->port_count; channel++, port++)
+			drop_dtr_rts(port);
 	}
-	port = bp->ports;
-	bp->status |= BOARD_ACTIVE;
-	for (channel = 0; channel < bp->port_count; channel++, port++)
-		drop_dtr_rts(port);
-	spin_unlock_irqrestore(&bp->card_lock, flags);
+	bp->status |= BOARD_ACTIVE | BOARD_INIT;
 }
 
-static int isicom_setup_port(struct tty_struct *tty)
+/* Activate and thus setup board are protected from races against shutdown
+   by the tty_port mutex */
+
+static int isicom_activate(struct tty_port *tport, struct tty_struct *tty)
 {
-	struct isi_port *port = tty->driver_data;
+	struct isi_port *port = container_of(tport, struct isi_port, port);
 	struct isi_board *card = port->card;
 	unsigned long flags;
 
-	if (port->port.flags & ASYNC_INITIALIZED)
-		return 0;
-	if (tty_port_alloc_xmit_buf(&port->port) < 0)
+	if (tty_port_alloc_xmit_buf(tport) < 0)
 		return -ENOMEM;
 
 	spin_lock_irqsave(&card->card_lock, flags);
-	clear_bit(TTY_IO_ERROR, &tty->flags);
-	if (port->port.count == 1)
-		card->count++;
+	isicom_setup_board(card);
 
 	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
 
@@ -832,9 +827,7 @@ static int isicom_setup_port(struct tty_struct *tty)
 		outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base);
 		InterruptTheCard(card->base);
 	}
-
 	isicom_config_port(tty);
-	port->port.flags |= ASYNC_INITIALIZED;
 	spin_unlock_irqrestore(&card->card_lock, flags);
 
 	return 0;
@@ -871,85 +864,37 @@ static struct tty_port *isicom_find_port(struct tty_struct *tty)
 
 	return &port->port;
 }
-	
+
 static int isicom_open(struct tty_struct *tty, struct file *filp)
 {
 	struct isi_port *port;
 	struct isi_board *card;
 	struct tty_port *tport;
-	int error = 0;
 
 	tport = isicom_find_port(tty);
 	if (tport == NULL)
 		return -ENODEV;
 	port = container_of(tport, struct isi_port, port);
 	card = &isi_card[BOARD(tty->index)];
-	isicom_setup_board(card);
 
-	/* FIXME: locking on port.count etc */
-	port->port.count++;
-	tty->driver_data = port;
-	tty_port_tty_set(&port->port, tty);
-	/* FIXME: Locking on Initialized flag */
-	if (!test_bit(ASYNCB_INITIALIZED, &tport->flags))
-		error = isicom_setup_port(tty);
-	if (error == 0)
-		error = tty_port_block_til_ready(&port->port, tty, filp);
-	return error;
+	return tty_port_open(tport, tty, filp);
 }
 
 /* close et all */
 
-static inline void isicom_shutdown_board(struct isi_board *bp)
-{
-	if (bp->status & BOARD_ACTIVE)
-		bp->status &= ~BOARD_ACTIVE;
-}
-
 /* card->lock HAS to be held */
 static void isicom_shutdown_port(struct isi_port *port)
 {
 	struct isi_board *card = port->card;
-	struct tty_struct *tty;
-
-	tty = tty_port_tty_get(&port->port);
-
-	if (!(port->port.flags & ASYNC_INITIALIZED)) {
-		tty_kref_put(tty);
-		return;
-	}
-
-	tty_port_free_xmit_buf(&port->port);
-	port->port.flags &= ~ASYNC_INITIALIZED;
-	/* 3rd October 2000 : Vinayak P Risbud */
-	tty_port_tty_set(&port->port, NULL);
-
-	/*Fix done by Anil .S on 30-04-2001
-	remote login through isi port has dtr toggle problem
-	due to which the carrier drops before the password prompt
-	appears on the remote end. Now we drop the dtr only if the
-	HUPCL(Hangup on close) flag is set for the tty*/
-
-	if (C_HUPCL(tty))
-		/* drop dtr on this port */
-		drop_dtr(port);
-
-	/* any other port uninits  */
-	if (tty)
-		set_bit(TTY_IO_ERROR, &tty->flags);
 
 	if (--card->count < 0) {
 		pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n",
 			card->base, card->count);
 		card->count = 0;
 	}
-
-	/* last port was closed, shutdown that boad too */
-	if (C_HUPCL(tty)) {
-		if (!card->count)
-			isicom_shutdown_board(card);
-	}
-	tty_kref_put(tty);
+	/* last port was closed, shutdown that board too */
+	if (!card->count)
+		card->status &= BOARD_ACTIVE;
 }
 
 static void isicom_flush_buffer(struct tty_struct *tty)
@@ -968,7 +913,7 @@ static void isicom_flush_buffer(struct tty_struct *tty)
 	tty_wakeup(tty);
 }
 
-static void isicom_close_port(struct tty_port *port)
+static void isicom_shutdown(struct tty_port *port)
 {
 	struct isi_port *ip = container_of(port, struct isi_port, port);
 	struct isi_board *card = ip->card;
@@ -977,12 +922,11 @@ static void isicom_close_port(struct tty_port *port)
 	/* indicate to the card that no more data can be received
 	   on this port */
 	spin_lock_irqsave(&card->card_lock, flags);
-	if (port->flags & ASYNC_INITIALIZED) {
-		card->port_status &= ~(1 << ip->channel);
-		outw(card->port_status, card->base + 0x02);
-	}
+	card->port_status &= ~(1 << ip->channel);
+	outw(card->port_status, card->base + 0x02);
 	isicom_shutdown_port(ip);
 	spin_unlock_irqrestore(&card->card_lock, flags);
+	tty_port_free_xmit_buf(port);
 }
 
 static void isicom_close(struct tty_struct *tty, struct file *filp)
@@ -991,12 +935,7 @@ static void isicom_close(struct tty_struct *tty, struct file *filp)
 	struct tty_port *port = &ip->port;
 	if (isicom_paranoia_check(ip, tty->name, "isicom_close"))
 		return;
-
-	if (tty_port_close_start(port, tty, filp) == 0)
-		return;
-	isicom_close_port(port);
-	isicom_flush_buffer(tty);
-	tty_port_close_end(port, tty);
+	tty_port_close(port, tty, filp);
 }
 
 /* write et all */
@@ -1326,15 +1265,9 @@ static void isicom_start(struct tty_struct *tty)
 static void isicom_hangup(struct tty_struct *tty)
 {
 	struct isi_port *port = tty->driver_data;
-	unsigned long flags;
 
 	if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
 		return;
-
-	spin_lock_irqsave(&port->card->card_lock, flags);
-	isicom_shutdown_port(port);
-	spin_unlock_irqrestore(&port->card->card_lock, flags);
-
 	tty_port_hangup(&port->port);
 }
 
@@ -1367,6 +1300,8 @@ static const struct tty_operations isicom_ops = {
 static const struct tty_port_operations isicom_port_ops = {
 	.carrier_raised		= isicom_carrier_raised,
 	.dtr_rts		= isicom_dtr_rts,
+	.activate		= isicom_activate,
+	.shutdown		= isicom_shutdown,
 };
 
 static int __devinit reset_card(struct pci_dev *pdev,
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 402838f4083e..4cd6c527ee41 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -213,7 +213,6 @@ static int		stli_shared;
  *	with the slave. Most of them need to be updated atomically, so always
  *	use the bit setting operations (unless protected by cli/sti).
  */
-#define	ST_INITIALIZING	1
 #define	ST_OPENING	2
 #define	ST_CLOSING	3
 #define	ST_CMDING	4
@@ -621,7 +620,7 @@ static int	stli_brdinit(struct stlibrd *brdp);
 static int	stli_startbrd(struct stlibrd *brdp);
 static ssize_t	stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp);
 static ssize_t	stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp);
-static int	stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
+static long	stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg);
 static void	stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp);
 static void	stli_poll(unsigned long arg);
 static int	stli_hostcmd(struct stlibrd *brdp, struct stliport *portp);
@@ -704,7 +703,7 @@ static const struct file_operations	stli_fsiomem = {
 	.owner		= THIS_MODULE,
 	.read		= stli_memread,
 	.write		= stli_memwrite,
-	.ioctl		= stli_memioctl,
+	.unlocked_ioctl	= stli_memioctl,
 };
 
 /*****************************************************************************/
@@ -783,13 +782,32 @@ static int stli_parsebrd(struct stlconf *confp, char **argp)
 
 /*****************************************************************************/
 
+/*
+ *	On the first open of the device setup the port hardware, and
+ *	initialize the per port data structure. Since initializing the port
+ *	requires several commands to the board we will need to wait for any
+ *	other open that is already initializing the port.
+ *
+ *	Locking: protected by the port mutex.
+ */
+
+static int stli_activate(struct tty_port *port, struct tty_struct *tty)
+{
+	struct stliport *portp = container_of(port, struct stliport, port);
+	struct stlibrd *brdp = stli_brds[portp->brdnr];
+	int rc;
+
+	if ((rc = stli_initopen(tty, brdp, portp)) >= 0)
+		clear_bit(TTY_IO_ERROR, &tty->flags);
+	wake_up_interruptible(&portp->raw_wait);
+	return rc;
+}
+
 static int stli_open(struct tty_struct *tty, struct file *filp)
 {
 	struct stlibrd *brdp;
 	struct stliport *portp;
-	struct tty_port *port;
 	unsigned int minordev, brdnr, portnr;
-	int rc;
 
 	minordev = tty->index;
 	brdnr = MINOR2BRD(minordev);
@@ -809,95 +827,56 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
 		return -ENODEV;
 	if (portp->devnr < 1)
 		return -ENODEV;
-	port = &portp->port;
-
-/*
- *	On the first open of the device setup the port hardware, and
- *	initialize the per port data structure. Since initializing the port
- *	requires several commands to the board we will need to wait for any
- *	other open that is already initializing the port.
- *
- *	Review - locking
- */
-	tty_port_tty_set(port, tty);
-	tty->driver_data = portp;
-	port->count++;
-
-	wait_event_interruptible(portp->raw_wait,
-			!test_bit(ST_INITIALIZING, &portp->state));
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-
-	if ((portp->port.flags & ASYNC_INITIALIZED) == 0) {
-		set_bit(ST_INITIALIZING, &portp->state);
-		if ((rc = stli_initopen(tty, brdp, portp)) >= 0) {
-			/* Locking */
-			port->flags |= ASYNC_INITIALIZED;
-			clear_bit(TTY_IO_ERROR, &tty->flags);
-		}
-		clear_bit(ST_INITIALIZING, &portp->state);
-		wake_up_interruptible(&portp->raw_wait);
-		if (rc < 0)
-			return rc;
-	}
-	return tty_port_block_til_ready(&portp->port, tty, filp);
+	return tty_port_open(&portp->port, tty, filp);
 }
 
+
 /*****************************************************************************/
 
-static void stli_close(struct tty_struct *tty, struct file *filp)
+static void stli_shutdown(struct tty_port *port)
 {
 	struct stlibrd *brdp;
-	struct stliport *portp;
-	struct tty_port *port;
+	unsigned long ftype;
 	unsigned long flags;
+	struct stliport *portp = container_of(port, struct stliport, port);
 
-	portp = tty->driver_data;
-	if (portp == NULL)
+	if (portp->brdnr >= stli_nrbrds)
 		return;
-	port = &portp->port;
-
-	if (tty_port_close_start(port, tty, filp) == 0)
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == NULL)
 		return;
 
-/*
- *	May want to wait for data to drain before closing. The BUSY flag
- *	keeps track of whether we are still transmitting or not. It is
- *	updated by messages from the slave - indicating when all chars
- *	really have drained.
- */
- 	spin_lock_irqsave(&stli_lock, flags);
-	if (tty == stli_txcooktty)
-		stli_flushchars(tty);
-	spin_unlock_irqrestore(&stli_lock, flags);
-
-	/* We end up doing this twice for the moment. This needs looking at
-	   eventually. Note we still use portp->closing_wait as a result */
-	if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-		tty_wait_until_sent(tty, portp->closing_wait);
+	/*
+	 *	May want to wait for data to drain before closing. The BUSY
+	 *	flag keeps track of whether we are still transmitting or not.
+	 *	It is updated by messages from the slave - indicating when all
+	 *	chars really have drained.
+	 */
 
-	/* FIXME: port locking here needs attending to */
-	port->flags &= ~ASYNC_INITIALIZED;
+	if (!test_bit(ST_CLOSING, &portp->state))
+		stli_rawclose(brdp, portp, 0, 0);
 
-	brdp = stli_brds[portp->brdnr];
-	stli_rawclose(brdp, portp, 0, 0);
-	if (tty->termios->c_cflag & HUPCL) {
-		stli_mkasysigs(&portp->asig, 0, 0);
-		if (test_bit(ST_CMDING, &portp->state))
-			set_bit(ST_DOSIGS, &portp->state);
-		else
-			stli_sendcmd(brdp, portp, A_SETSIGNALS, &portp->asig,
-				sizeof(asysigs_t), 0);
-	}
+ 	spin_lock_irqsave(&stli_lock, flags);
 	clear_bit(ST_TXBUSY, &portp->state);
 	clear_bit(ST_RXSTOP, &portp->state);
-	set_bit(TTY_IO_ERROR, &tty->flags);
-	tty_ldisc_flush(tty);
-	set_bit(ST_DOFLUSHRX, &portp->state);
-	stli_flushbuffer(tty);
+	spin_unlock_irqrestore(&stli_lock, flags);
 
-	tty_port_close_end(port, tty);
-	tty_port_tty_set(port, NULL);
+	ftype = FLUSHTX | FLUSHRX;
+	stli_cmdwait(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0);
+}
+
+static void stli_close(struct tty_struct *tty, struct file *filp)
+{
+	struct stliport *portp = tty->driver_data;
+	unsigned long flags;
+	if (portp == NULL)
+		return;
+ 	spin_lock_irqsave(&stli_lock, flags);
+	/*	Flush any internal buffering out first */
+	if (tty == stli_txcooktty)
+		stli_flushchars(tty);
+	spin_unlock_irqrestore(&stli_lock, flags);
+	tty_port_close(&portp->port, tty, filp);
 }
 
 /*****************************************************************************/
@@ -1724,6 +1703,7 @@ static void stli_start(struct tty_struct *tty)
 
 /*****************************************************************************/
 
+
 /*
  *	Hangup this port. This is pretty much like closing the port, only
  *	a little more brutal. No waiting for data to drain. Shutdown the
@@ -1733,47 +1713,8 @@ static void stli_start(struct tty_struct *tty)
 
 static void stli_hangup(struct tty_struct *tty)
 {
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	struct tty_port *port;
-	unsigned long flags;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	if (portp->brdnr >= stli_nrbrds)
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-	port = &portp->port;
-
-	spin_lock_irqsave(&port->lock, flags);
-	port->flags &= ~ASYNC_INITIALIZED;
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	if (!test_bit(ST_CLOSING, &portp->state))
-		stli_rawclose(brdp, portp, 0, 0);
-
-	spin_lock_irqsave(&stli_lock, flags);
-	if (tty->termios->c_cflag & HUPCL) {
-		stli_mkasysigs(&portp->asig, 0, 0);
-		if (test_bit(ST_CMDING, &portp->state)) {
-			set_bit(ST_DOSIGS, &portp->state);
-			set_bit(ST_DOFLUSHTX, &portp->state);
-			set_bit(ST_DOFLUSHRX, &portp->state);
-		} else {
-			stli_sendcmd(brdp, portp, A_SETSIGNALSF,
-				&portp->asig, sizeof(asysigs_t), 0);
-		}
-	}
-
-	clear_bit(ST_TXBUSY, &portp->state);
-	clear_bit(ST_RXSTOP, &portp->state);
-	set_bit(TTY_IO_ERROR, &tty->flags);
-	spin_unlock_irqrestore(&stli_lock, flags);
-
-	tty_port_hangup(port);
+	struct stliport *portp = tty->driver_data;
+	tty_port_hangup(&portp->port);
 }
 
 /*****************************************************************************/
@@ -4311,7 +4252,7 @@ static int stli_getbrdstruct(struct stlibrd __user *arg)
  *	reset it, and start/stop it.
  */
 
-static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
+static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
 {
 	struct stlibrd *brdp;
 	int brdnr, rc, done;
@@ -4356,7 +4297,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
  *	Now handle the board specific ioctls. These all depend on the
  *	minor number of the device they were called from.
  */
-	brdnr = iminor(ip);
+	brdnr = iminor(fp->f_dentry->d_inode);
 	if (brdnr >= STL_MAXBRDS)
 		return -ENODEV;
 	brdp = stli_brds[brdnr];
@@ -4420,6 +4361,8 @@ static const struct tty_operations stli_ops = {
 static const struct tty_port_operations stli_port_ops = {
 	.carrier_raised = stli_carrier_raised,
 	.dtr_rts = stli_dtr_rts,
+	.activate = stli_activate,
+	.shutdown = stli_shutdown,
 };
 
 /*****************************************************************************/
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index dd0083bbb64a..63ee3bbc1ce4 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -34,7 +34,6 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/major.h>
-#include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
@@ -139,7 +138,7 @@ struct moxa_port {
 	int cflag;
 	unsigned long statusflags;
 
-	u8 DCDState;
+	u8 DCDState;		/* Protected by the port lock */
 	u8 lineCtrl;
 	u8 lowChkFlag;
 };
@@ -151,10 +150,9 @@ struct mon_str {
 };
 
 /* statusflags */
-#define TXSTOPPED	0x1
-#define LOWWAIT 	0x2
-#define EMPTYWAIT	0x4
-#define THROTTLE	0x8
+#define TXSTOPPED	1
+#define LOWWAIT 	2
+#define EMPTYWAIT	3
 
 #define SERIAL_DO_RESTART
 
@@ -165,6 +163,7 @@ static struct mon_str moxaLog;
 static unsigned int moxaFuncTout = HZ / 2;
 static unsigned int moxaLowWaterChk;
 static DEFINE_MUTEX(moxa_openlock);
+static DEFINE_SPINLOCK(moxa_lock);
 /* Variables for insmod */
 #ifdef MODULE
 static unsigned long baseaddr[MAX_BOARDS];
@@ -194,8 +193,6 @@ static int moxa_write(struct tty_struct *, const unsigned char *, int);
 static int moxa_write_room(struct tty_struct *);
 static void moxa_flush_buffer(struct tty_struct *);
 static int moxa_chars_in_buffer(struct tty_struct *);
-static void moxa_throttle(struct tty_struct *);
-static void moxa_unthrottle(struct tty_struct *);
 static void moxa_set_termios(struct tty_struct *, struct ktermios *);
 static void moxa_stop(struct tty_struct *);
 static void moxa_start(struct tty_struct *);
@@ -205,9 +202,9 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
 			 unsigned int set, unsigned int clear);
 static void moxa_poll(unsigned long);
 static void moxa_set_tty_param(struct tty_struct *, struct ktermios *);
-static void moxa_setup_empty_event(struct tty_struct *);
-static void moxa_shut_down(struct tty_struct *);
+static void moxa_shutdown(struct tty_port *);
 static int moxa_carrier_raised(struct tty_port *);
+static void moxa_dtr_rts(struct tty_port *, int);
 /*
  * moxa board interface functions:
  */
@@ -234,6 +231,8 @@ static void MoxaSetFifo(struct moxa_port *port, int enable);
  * I/O functions
  */
 
+static DEFINE_SPINLOCK(moxafunc_lock);
+
 static void moxa_wait_finish(void __iomem *ofsAddr)
 {
 	unsigned long end = jiffies + moxaFuncTout;
@@ -247,9 +246,25 @@ static void moxa_wait_finish(void __iomem *ofsAddr)
 
 static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg)
 {
+        unsigned long flags;
+        spin_lock_irqsave(&moxafunc_lock, flags);
 	writew(arg, ofsAddr + FuncArg);
 	writew(cmd, ofsAddr + FuncCode);
 	moxa_wait_finish(ofsAddr);
+	spin_unlock_irqrestore(&moxafunc_lock, flags);
+}
+
+static int moxafuncret(void __iomem *ofsAddr, u16 cmd, u16 arg)
+{
+        unsigned long flags;
+        u16 ret;
+        spin_lock_irqsave(&moxafunc_lock, flags);
+	writew(arg, ofsAddr + FuncArg);
+	writew(cmd, ofsAddr + FuncCode);
+	moxa_wait_finish(ofsAddr);
+	ret = readw(ofsAddr + FuncArg);
+	spin_unlock_irqrestore(&moxafunc_lock, flags);
+	return ret;
 }
 
 static void moxa_low_water_check(void __iomem *ofsAddr)
@@ -299,22 +314,20 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file,
 		struct moxa_port *p;
 		unsigned int i, j;
 
-		mutex_lock(&moxa_openlock);
 		for (i = 0; i < MAX_BOARDS; i++) {
 			p = moxa_boards[i].ports;
 			for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
 				memset(&tmp, 0, sizeof(tmp));
+				spin_lock_bh(&moxa_lock);
 				if (moxa_boards[i].ready) {
 					tmp.inq = MoxaPortRxQueue(p);
 					tmp.outq = MoxaPortTxQueue(p);
 				}
-				if (copy_to_user(argm, &tmp, sizeof(tmp))) {
-					mutex_unlock(&moxa_openlock);
+				spin_unlock_bh(&moxa_lock);
+				if (copy_to_user(argm, &tmp, sizeof(tmp)))
 					return -EFAULT;
-				}
 			}
 		}
-		mutex_unlock(&moxa_openlock);
 		break;
 	} case MOXA_GET_OQUEUE:
 		status = MoxaPortTxQueue(ch);
@@ -330,16 +343,20 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file,
 		struct moxa_port *p;
 		unsigned int i, j;
 
-		mutex_lock(&moxa_openlock);
 		for (i = 0; i < MAX_BOARDS; i++) {
 			p = moxa_boards[i].ports;
 			for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
 				struct tty_struct *ttyp;
 				memset(&tmp, 0, sizeof(tmp));
-				if (!moxa_boards[i].ready)
+				spin_lock_bh(&moxa_lock);
+				if (!moxa_boards[i].ready) {
+				        spin_unlock_bh(&moxa_lock);
 					goto copy;
+                                }
 
 				status = MoxaPortLineStatus(p);
+				spin_unlock_bh(&moxa_lock);
+
 				if (status & 1)
 					tmp.cts = 1;
 				if (status & 2)
@@ -354,24 +371,21 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file,
 					tmp.cflag = ttyp->termios->c_cflag;
 				tty_kref_put(tty);
 copy:
-				if (copy_to_user(argm, &tmp, sizeof(tmp))) {
-					mutex_unlock(&moxa_openlock);
+				if (copy_to_user(argm, &tmp, sizeof(tmp)))
 					return -EFAULT;
-				}
 			}
 		}
-		mutex_unlock(&moxa_openlock);
 		break;
 	}
 	case TIOCGSERIAL:
-		mutex_lock(&moxa_openlock);
+	        mutex_lock(&ch->port.mutex);
 		ret = moxa_get_serial_info(ch, argp);
-		mutex_unlock(&moxa_openlock);
+		mutex_unlock(&ch->port.mutex);
 		break;
 	case TIOCSSERIAL:
-		mutex_lock(&moxa_openlock);
+	        mutex_lock(&ch->port.mutex);
 		ret = moxa_set_serial_info(ch, argp);
-		mutex_unlock(&moxa_openlock);
+		mutex_unlock(&ch->port.mutex);
 		break;
 	default:
 		ret = -ENOIOCTLCMD;
@@ -396,8 +410,6 @@ static const struct tty_operations moxa_ops = {
 	.flush_buffer = moxa_flush_buffer,
 	.chars_in_buffer = moxa_chars_in_buffer,
 	.ioctl = moxa_ioctl,
-	.throttle = moxa_throttle,
-	.unthrottle = moxa_unthrottle,
 	.set_termios = moxa_set_termios,
 	.stop = moxa_stop,
 	.start = moxa_start,
@@ -409,11 +421,12 @@ static const struct tty_operations moxa_ops = {
 
 static const struct tty_port_operations moxa_port_ops = {
 	.carrier_raised = moxa_carrier_raised,
+	.dtr_rts = moxa_dtr_rts,
+	.shutdown = moxa_shutdown,
 };
 
 static struct tty_driver *moxaDriver;
 static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0);
-static DEFINE_SPINLOCK(moxa_lock);
 
 /*
  * HW init
@@ -1112,14 +1125,12 @@ static void __exit moxa_exit(void)
 module_init(moxa_init);
 module_exit(moxa_exit);
 
-static void moxa_close_port(struct tty_struct *tty)
+static void moxa_shutdown(struct tty_port *port)
 {
-	struct moxa_port *ch = tty->driver_data;
-	moxa_shut_down(tty);
+	struct moxa_port *ch = container_of(port, struct moxa_port, port);
+        MoxaPortDisable(ch);
 	MoxaPortFlushData(ch, 2);
-	ch->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-	tty->driver_data = NULL;
-	tty_port_tty_set(&ch->port, NULL);
+	clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
 }
 
 static int moxa_carrier_raised(struct tty_port *port)
@@ -1127,45 +1138,19 @@ static int moxa_carrier_raised(struct tty_port *port)
 	struct moxa_port *ch = container_of(port, struct moxa_port, port);
 	int dcd;
 
-	spin_lock_bh(&moxa_lock);
+	spin_lock_irq(&port->lock);
 	dcd = ch->DCDState;
-	spin_unlock_bh(&moxa_lock);
+	spin_unlock_irq(&port->lock);
 	return dcd;
 }
 
-static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
-			    struct moxa_port *ch)
+static void moxa_dtr_rts(struct tty_port *port, int onoff)
 {
-	struct tty_port *port = &ch->port;
-	DEFINE_WAIT(wait);
-	int retval = 0;
-	u8 dcd;
-
-	while (1) {
-		prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp)) {
-#ifdef SERIAL_DO_RESTART
-			retval = -ERESTARTSYS;
-#else
-			retval = -EAGAIN;
-#endif
-			break;
-		}
-		dcd = tty_port_carrier_raised(port);
-		if (dcd)
-			break;
-
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-		schedule();
-	}
-	finish_wait(&port->open_wait, &wait);
-
-	return retval;
+	struct moxa_port *ch = container_of(port, struct moxa_port, port);
+	MoxaPortLineCtrl(ch, onoff, onoff);
 }
 
+
 static int moxa_open(struct tty_struct *tty, struct file *filp)
 {
 	struct moxa_board_conf *brd;
@@ -1194,6 +1179,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
 	ch->port.count++;
 	tty->driver_data = ch;
 	tty_port_tty_set(&ch->port, tty);
+	mutex_lock(&ch->port.mutex);
 	if (!(ch->port.flags & ASYNC_INITIALIZED)) {
 		ch->statusflags = 0;
 		moxa_set_tty_param(tty, tty->termios);
@@ -1202,58 +1188,20 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
 		MoxaSetFifo(ch, ch->type == PORT_16550A);
 		ch->port.flags |= ASYNC_INITIALIZED;
 	}
+	mutex_unlock(&ch->port.mutex);
 	mutex_unlock(&moxa_openlock);
 
-	retval = 0;
-	if (!(filp->f_flags & O_NONBLOCK) && !C_CLOCAL(tty))
-		retval = moxa_block_till_ready(tty, filp, ch);
-	mutex_lock(&moxa_openlock);
-	if (retval) {
-		if (ch->port.count) /* 0 means already hung up... */
-			if (--ch->port.count == 0)
-				moxa_close_port(tty);
-	} else
-		ch->port.flags |= ASYNC_NORMAL_ACTIVE;
-	mutex_unlock(&moxa_openlock);
-
+	retval = tty_port_block_til_ready(&ch->port, tty, filp);
+	if (retval == 0)
+	        set_bit(ASYNCB_NORMAL_ACTIVE, &ch->port.flags);
 	return retval;
 }
 
 static void moxa_close(struct tty_struct *tty, struct file *filp)
 {
-	struct moxa_port *ch;
-	int port;
-
-	port = tty->index;
-	if (port == MAX_PORTS || tty_hung_up_p(filp))
-		return;
-
-	mutex_lock(&moxa_openlock);
-	ch = tty->driver_data;
-	if (ch == NULL)
-		goto unlock;
-	if (tty->count == 1 && ch->port.count != 1) {
-		printk(KERN_WARNING "moxa_close: bad serial port count; "
-			"tty->count is 1, ch->port.count is %d\n", ch->port.count);
-		ch->port.count = 1;
-	}
-	if (--ch->port.count < 0) {
-		printk(KERN_WARNING "moxa_close: bad serial port count, "
-			"device=%s\n", tty->name);
-		ch->port.count = 0;
-	}
-	if (ch->port.count)
-		goto unlock;
-
+	struct moxa_port *ch = tty->driver_data;
 	ch->cflag = tty->termios->c_cflag;
-	if (ch->port.flags & ASYNC_INITIALIZED) {
-		moxa_setup_empty_event(tty);
-		tty_wait_until_sent(tty, 30 * HZ);	/* 30 seconds timeout */
-	}
-
-	moxa_close_port(tty);
-unlock:
-	mutex_unlock(&moxa_openlock);
+	tty_port_close(&ch->port, tty, filp);
 }
 
 static int moxa_write(struct tty_struct *tty,
@@ -1269,7 +1217,7 @@ static int moxa_write(struct tty_struct *tty,
 	len = MoxaPortWriteData(tty, buf, count);
 	spin_unlock_bh(&moxa_lock);
 
-	ch->statusflags |= LOWWAIT;
+	set_bit(LOWWAIT, &ch->statusflags);
 	return len;
 }
 
@@ -1300,40 +1248,21 @@ static int moxa_chars_in_buffer(struct tty_struct *tty)
 	struct moxa_port *ch = tty->driver_data;
 	int chars;
 
-	/*
-	 * Sigh...I have to check if driver_data is NULL here, because
-	 * if an open() fails, the TTY subsystem eventually calls
-	 * tty_wait_until_sent(), which calls the driver's chars_in_buffer()
-	 * routine.  And since the open() failed, we return 0 here.  TDJ
-	 */
-	if (ch == NULL)
-		return 0;
-	lock_kernel();
 	chars = MoxaPortTxQueue(ch);
-	if (chars) {
+	if (chars)
 		/*
 		 * Make it possible to wakeup anything waiting for output
 		 * in tty_ioctl.c, etc.
 		 */
-		if (!(ch->statusflags & EMPTYWAIT))
-			moxa_setup_empty_event(tty);
-	}
-	unlock_kernel();
+        	set_bit(EMPTYWAIT, &ch->statusflags);
 	return chars;
 }
 
 static int moxa_tiocmget(struct tty_struct *tty, struct file *file)
 {
-	struct moxa_port *ch;
+	struct moxa_port *ch = tty->driver_data;
 	int flag = 0, dtr, rts;
 
-	mutex_lock(&moxa_openlock);
-	ch = tty->driver_data;
-	if (!ch) {
-		mutex_unlock(&moxa_openlock);
-		return -EINVAL;
-	}
-
 	MoxaPortGetLineOut(ch, &dtr, &rts);
 	if (dtr)
 		flag |= TIOCM_DTR;
@@ -1346,7 +1275,6 @@ static int moxa_tiocmget(struct tty_struct *tty, struct file *file)
 		flag |= TIOCM_DSR;
 	if (dtr & 4)
 		flag |= TIOCM_CD;
-	mutex_unlock(&moxa_openlock);
 	return flag;
 }
 
@@ -1379,20 +1307,6 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
 	return 0;
 }
 
-static void moxa_throttle(struct tty_struct *tty)
-{
-	struct moxa_port *ch = tty->driver_data;
-
-	ch->statusflags |= THROTTLE;
-}
-
-static void moxa_unthrottle(struct tty_struct *tty)
-{
-	struct moxa_port *ch = tty->driver_data;
-
-	ch->statusflags &= ~THROTTLE;
-}
-
 static void moxa_set_termios(struct tty_struct *tty,
 		struct ktermios *old_termios)
 {
@@ -1412,7 +1326,7 @@ static void moxa_stop(struct tty_struct *tty)
 	if (ch == NULL)
 		return;
 	MoxaPortTxDisable(ch);
-	ch->statusflags |= TXSTOPPED;
+	set_bit(TXSTOPPED, &ch->statusflags);
 }
 
 
@@ -1427,38 +1341,32 @@ static void moxa_start(struct tty_struct *tty)
 		return;
 
 	MoxaPortTxEnable(ch);
-	ch->statusflags &= ~TXSTOPPED;
+	clear_bit(TXSTOPPED, &ch->statusflags);
 }
 
 static void moxa_hangup(struct tty_struct *tty)
 {
-	struct moxa_port *ch;
-
-	mutex_lock(&moxa_openlock);
-	ch = tty->driver_data;
-	if (ch == NULL) {
-		mutex_unlock(&moxa_openlock);
-		return;
-	}
-	ch->port.count = 0;
-	moxa_close_port(tty);
-	mutex_unlock(&moxa_openlock);
-
-	wake_up_interruptible(&ch->port.open_wait);
+	struct moxa_port *ch = tty->driver_data;
+	tty_port_hangup(&ch->port);
 }
 
 static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
 {
 	struct tty_struct *tty;
+	unsigned long flags;
 	dcd = !!dcd;
 
+	spin_lock_irqsave(&p->port.lock, flags);
 	if (dcd != p->DCDState) {
+        	p->DCDState = dcd;
+        	spin_unlock_irqrestore(&p->port.lock, flags);
 		tty = tty_port_tty_get(&p->port);
 		if (tty && C_CLOCAL(tty) && !dcd)
 			tty_hangup(tty);
 		tty_kref_put(tty);
 	}
-	p->DCDState = dcd;
+	else
+		spin_unlock_irqrestore(&p->port.lock, flags);
 }
 
 static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
@@ -1470,24 +1378,24 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
 	u16 intr;
 
 	if (tty) {
-		if ((p->statusflags & EMPTYWAIT) &&
+		if (test_bit(EMPTYWAIT, &p->statusflags) &&
 				MoxaPortTxQueue(p) == 0) {
-			p->statusflags &= ~EMPTYWAIT;
+			clear_bit(EMPTYWAIT, &p->statusflags);
 			tty_wakeup(tty);
 		}
-		if ((p->statusflags & LOWWAIT) && !tty->stopped &&
+		if (test_bit(LOWWAIT, &p->statusflags) && !tty->stopped &&
 				MoxaPortTxQueue(p) <= WAKEUP_CHARS) {
-			p->statusflags &= ~LOWWAIT;
+			clear_bit(LOWWAIT, &p->statusflags);
 			tty_wakeup(tty);
 		}
 
-		if (inited && !(p->statusflags & THROTTLE) &&
+		if (inited && !test_bit(TTY_THROTTLED, &tty->flags) &&
 				MoxaPortRxQueue(p) > 0) { /* RX */
 			MoxaPortReadData(p);
 			tty_schedule_flip(tty);
 		}
 	} else {
-		p->statusflags &= ~EMPTYWAIT;
+		clear_bit(EMPTYWAIT, &p->statusflags);
 		MoxaPortFlushData(p, 0); /* flush RX */
 	}
 
@@ -1588,35 +1496,6 @@ static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_term
 	tty_encode_baud_rate(tty, baud, baud);
 }
 
-static void moxa_setup_empty_event(struct tty_struct *tty)
-{
-	struct moxa_port *ch = tty->driver_data;
-
-	spin_lock_bh(&moxa_lock);
-	ch->statusflags |= EMPTYWAIT;
-	spin_unlock_bh(&moxa_lock);
-}
-
-static void moxa_shut_down(struct tty_struct *tty)
-{
-	struct moxa_port *ch = tty->driver_data;
-
-	if (!(ch->port.flags & ASYNC_INITIALIZED))
-		return;
-
-	MoxaPortDisable(ch);
-
-	/*
-	 * If we're a modem control device and HUPCL is on, drop RTS & DTR.
-	 */
-	if (C_HUPCL(tty))
-		MoxaPortLineCtrl(ch, 0, 0);
-
-	spin_lock_bh(&moxa_lock);
-	ch->port.flags &= ~ASYNC_INITIALIZED;
-	spin_unlock_bh(&moxa_lock);
-}
-
 /*****************************************************************************
  *	Driver level functions: 					     *
  *****************************************************************************/
@@ -1918,10 +1797,12 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio,
 	baud = MoxaPortSetBaud(port, baud);
 
 	if (termio->c_iflag & (IXON | IXOFF | IXANY)) {
+	        spin_lock_irq(&moxafunc_lock);
 		writeb(termio->c_cc[VSTART], ofsAddr + FuncArg);
 		writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1);
 		writeb(FC_SetXonXoff, ofsAddr + FuncCode);
 		moxa_wait_finish(ofsAddr);
+		spin_unlock_irq(&moxafunc_lock);
 
 	}
 	return baud;
@@ -1974,18 +1855,14 @@ static int MoxaPortLineStatus(struct moxa_port *port)
 	int val;
 
 	ofsAddr = port->tableAddr;
-	if (MOXA_IS_320(port->board)) {
-		moxafunc(ofsAddr, FC_LineStatus, 0);
-		val = readw(ofsAddr + FuncArg);
-	} else {
+	if (MOXA_IS_320(port->board))
+		val = moxafuncret(ofsAddr, FC_LineStatus, 0);
+	else
 		val = readw(ofsAddr + FlagStat) >> 4;
-	}
 	val &= 0x0B;
 	if (val & 8)
 		val |= 4;
-	spin_lock_bh(&moxa_lock);
 	moxa_new_dcdstate(port, val & 8);
-	spin_unlock_bh(&moxa_lock);
 	val &= 7;
 	return val;
 }
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 5e28d39b9e81..3d923065d9a2 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -23,7 +23,6 @@
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
@@ -856,9 +855,9 @@ static void mxser_check_modem_status(struct tty_struct *tty,
 	}
 }
 
-static int mxser_startup(struct tty_struct *tty)
+static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
 {
-	struct mxser_port *info = tty->driver_data;
+	struct mxser_port *info = container_of(port, struct mxser_port, port);
 	unsigned long page;
 	unsigned long flags;
 
@@ -868,22 +867,13 @@ static int mxser_startup(struct tty_struct *tty)
 
 	spin_lock_irqsave(&info->slock, flags);
 
-	if (info->port.flags & ASYNC_INITIALIZED) {
-		free_page(page);
-		spin_unlock_irqrestore(&info->slock, flags);
-		return 0;
-	}
-
 	if (!info->ioaddr || !info->type) {
 		set_bit(TTY_IO_ERROR, &tty->flags);
 		free_page(page);
 		spin_unlock_irqrestore(&info->slock, flags);
 		return 0;
 	}
-	if (info->port.xmit_buf)
-		free_page(page);
-	else
-		info->port.xmit_buf = (unsigned char *) page;
+	info->port.xmit_buf = (unsigned char *) page;
 
 	/*
 	 * Clear the FIFO buffers and disable them
@@ -951,24 +941,19 @@ static int mxser_startup(struct tty_struct *tty)
 	 * and set the speed of the serial port
 	 */
 	mxser_change_speed(tty, NULL);
-	info->port.flags |= ASYNC_INITIALIZED;
 	spin_unlock_irqrestore(&info->slock, flags);
 
 	return 0;
 }
 
 /*
- * This routine will shutdown a serial port; interrupts maybe disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
+ * This routine will shutdown a serial port
  */
-static void mxser_shutdown(struct tty_struct *tty)
+static void mxser_shutdown_port(struct tty_port *port)
 {
-	struct mxser_port *info = tty->driver_data;
+	struct mxser_port *info = container_of(port, struct mxser_port, port);
 	unsigned long flags;
 
-	if (!(info->port.flags & ASYNC_INITIALIZED))
-		return;
-
 	spin_lock_irqsave(&info->slock, flags);
 
 	/*
@@ -978,7 +963,7 @@ static void mxser_shutdown(struct tty_struct *tty)
 	wake_up_interruptible(&info->port.delta_msr_wait);
 
 	/*
-	 * Free the IRQ, if necessary
+	 * Free the xmit buffer, if necessary
 	 */
 	if (info->port.xmit_buf) {
 		free_page((unsigned long) info->port.xmit_buf);
@@ -988,10 +973,6 @@ static void mxser_shutdown(struct tty_struct *tty)
 	info->IER = 0;
 	outb(0x00, info->ioaddr + UART_IER);
 
-	if (tty->termios->c_cflag & HUPCL)
-		info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);
-	outb(info->MCR, info->ioaddr + UART_MCR);
-
 	/* clear Rx/Tx FIFO's */
 	if (info->board->chip_flag)
 		outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT |
@@ -1004,9 +985,6 @@ static void mxser_shutdown(struct tty_struct *tty)
 	/* read data port to reset things */
 	(void) inb(info->ioaddr + UART_RX);
 
-	set_bit(TTY_IO_ERROR, &tty->flags);
-
-	info->port.flags &= ~ASYNC_INITIALIZED;
 
 	if (info->board->chip_flag)
 		SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr);
@@ -1023,8 +1001,7 @@ static void mxser_shutdown(struct tty_struct *tty)
 static int mxser_open(struct tty_struct *tty, struct file *filp)
 {
 	struct mxser_port *info;
-	unsigned long flags;
-	int retval, line;
+	int line;
 
 	line = tty->index;
 	if (line == MXSER_PORTS)
@@ -1035,23 +1012,7 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
 	if (!info->ioaddr)
 		return -ENODEV;
 
-	tty->driver_data = info;
-	tty_port_tty_set(&info->port, tty);
-	/*
-	 * Start up serial port
-	 */
-	spin_lock_irqsave(&info->port.lock, flags);
-	info->port.count++;
-	spin_unlock_irqrestore(&info->port.lock, flags);
-	retval = mxser_startup(tty);
-	if (retval)
-		return retval;
-
-	retval = tty_port_block_til_ready(&info->port, tty, filp);
-	if (retval)
-		return retval;
-
-	return 0;
+	return tty_port_open(&info->port, tty, filp);
 }
 
 static void mxser_flush_buffer(struct tty_struct *tty)
@@ -1075,19 +1036,11 @@ static void mxser_flush_buffer(struct tty_struct *tty)
 }
 
 
-static void mxser_close_port(struct tty_struct *tty, struct tty_port *port)
+static void mxser_close_port(struct tty_port *port)
 {
 	struct mxser_port *info = container_of(port, struct mxser_port, port);
 	unsigned long timeout;
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 *
-	 * FIXME: Can this go ?
-	 */
-	if (port->flags & ASYNC_NORMAL_ACTIVE)
-		info->normal_termios = *tty->termios;
-	/*
 	 * At this point we stop accepting input.  To do this, we
 	 * disable the receive line status interrupts, and tell the
 	 * interrupt driver to stop checking the data ready bit in the
@@ -1097,22 +1050,18 @@ static void mxser_close_port(struct tty_struct *tty, struct tty_port *port)
 	if (info->board->chip_flag)
 		info->IER &= ~MOXA_MUST_RECV_ISR;
 
-	if (port->flags & ASYNC_INITIALIZED) {
-		outb(info->IER, info->ioaddr + UART_IER);
-		/*
-		 * Before we drop DTR, make sure the UART transmitter
-		 * has completely drained; this is especially
-		 * important if there is a transmit FIFO!
-		 */
-		timeout = jiffies + HZ;
-		while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) {
-			schedule_timeout_interruptible(5);
-			if (time_after(jiffies, timeout))
-				break;
-		}
+	outb(info->IER, info->ioaddr + UART_IER);
+	/*
+	 * Before we drop DTR, make sure the UART transmitter
+	 * has completely drained; this is especially
+	 * important if there is a transmit FIFO!
+	 */
+	timeout = jiffies + HZ;
+	while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) {
+		schedule_timeout_interruptible(5);
+		if (time_after(jiffies, timeout))
+			break;
 	}
-	mxser_shutdown(tty);
-
 }
 
 /*
@@ -1130,8 +1079,12 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
 		return;
 	if (tty_port_close_start(port, tty, filp) == 0)
 		return;
-	mxser_close_port(tty, port);
+	mutex_lock(&port->mutex);
+	mxser_close_port(port);
 	mxser_flush_buffer(tty);
+	mxser_shutdown_port(port);
+	clear_bit(ASYNCB_INITIALIZED, &port->flags);
+	mutex_unlock(&port->mutex);
 	/* Right now the tty_port set is done outside of the close_end helper
 	   as we don't yet have everyone using refcounts */	
 	tty_port_close_end(port, tty);
@@ -1275,6 +1228,7 @@ static int mxser_set_serial_info(struct tty_struct *tty,
 		struct serial_struct __user *new_info)
 {
 	struct mxser_port *info = tty->driver_data;
+	struct tty_port *port = &info->port;
 	struct serial_struct new_serial;
 	speed_t baud;
 	unsigned long sl_flags;
@@ -1290,7 +1244,7 @@ static int mxser_set_serial_info(struct tty_struct *tty,
 			new_serial.port != info->ioaddr)
 		return -EINVAL;
 
-	flags = info->port.flags & ASYNC_SPD_MASK;
+	flags = port->flags & ASYNC_SPD_MASK;
 
 	if (!capable(CAP_SYS_ADMIN)) {
 		if ((new_serial.baud_base != info->baud_base) ||
@@ -1304,16 +1258,17 @@ static int mxser_set_serial_info(struct tty_struct *tty,
 		 * OK, past this point, all the error checking has been done.
 		 * At this point, we start making changes.....
 		 */
-		info->port.flags = ((info->port.flags & ~ASYNC_FLAGS) |
+		port->flags = ((port->flags & ~ASYNC_FLAGS) |
 				(new_serial.flags & ASYNC_FLAGS));
-		info->port.close_delay = new_serial.close_delay * HZ / 100;
-		info->port.closing_wait = new_serial.closing_wait * HZ / 100;
-		tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY)
-								? 1 : 0;
-		if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
+		port->close_delay = new_serial.close_delay * HZ / 100;
+		port->closing_wait = new_serial.closing_wait * HZ / 100;
+		tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
 				(new_serial.baud_base != info->baud_base ||
 				new_serial.custom_divisor !=
 				info->custom_divisor)) {
+			if (new_serial.custom_divisor == 0)
+				return -EINVAL;
 			baud = new_serial.baud_base / new_serial.custom_divisor;
 			tty_encode_baud_rate(tty, baud, baud);
 		}
@@ -1323,15 +1278,17 @@ static int mxser_set_serial_info(struct tty_struct *tty,
 
 	process_txrx_fifo(info);
 
-	if (info->port.flags & ASYNC_INITIALIZED) {
-		if (flags != (info->port.flags & ASYNC_SPD_MASK)) {
+	if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
+		if (flags != (port->flags & ASYNC_SPD_MASK)) {
 			spin_lock_irqsave(&info->slock, sl_flags);
 			mxser_change_speed(tty, NULL);
 			spin_unlock_irqrestore(&info->slock, sl_flags);
 		}
-	} else
-		retval = mxser_startup(tty);
-
+	} else {
+		retval = mxser_activate(port, tty);
+		if (retval == 0)
+			set_bit(ASYNCB_INITIALIZED, &port->flags);
+	}
 	return retval;
 }
 
@@ -1520,7 +1477,8 @@ static int __init mxser_read_register(int port, unsigned short *regs)
 
 static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
 {
-	struct mxser_port *port;
+	struct mxser_port *ip;
+	struct tty_port *port;
 	struct tty_struct *tty;
 	int result, status;
 	unsigned int i, j;
@@ -1536,38 +1494,39 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
 
 	case MOXA_CHKPORTENABLE:
 		result = 0;
-		lock_kernel();
 		for (i = 0; i < MXSER_BOARDS; i++)
 			for (j = 0; j < MXSER_PORTS_PER_BOARD; j++)
 				if (mxser_boards[i].ports[j].ioaddr)
 					result |= (1 << i);
-		unlock_kernel();
 		return put_user(result, (unsigned long __user *)argp);
 	case MOXA_GETDATACOUNT:
-		lock_kernel();
+		/* The receive side is locked by port->slock but it isn't
+		   clear that an exact snapshot is worth copying here */
 		if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log)))
 			ret = -EFAULT;
-		unlock_kernel();
 		return ret;
 	case MOXA_GETMSTATUS: {
 		struct mxser_mstatus ms, __user *msu = argp;
-		lock_kernel();
 		for (i = 0; i < MXSER_BOARDS; i++)
 			for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
-				port = &mxser_boards[i].ports[j];
+				ip = &mxser_boards[i].ports[j];
+				port = &ip->port;
 				memset(&ms, 0, sizeof(ms));
 
-				if (!port->ioaddr)
+				mutex_lock(&port->mutex);
+				if (!ip->ioaddr)
 					goto copy;
 				
-				tty = tty_port_tty_get(&port->port);
+				tty = tty_port_tty_get(port);
 
 				if (!tty || !tty->termios)
-					ms.cflag = port->normal_termios.c_cflag;
+					ms.cflag = ip->normal_termios.c_cflag;
 				else
 					ms.cflag = tty->termios->c_cflag;
 				tty_kref_put(tty);
-				status = inb(port->ioaddr + UART_MSR);
+				spin_lock_irq(&ip->slock);
+				status = inb(ip->ioaddr + UART_MSR);
+				spin_unlock_irq(&ip->slock);
 				if (status & UART_MSR_DCD)
 					ms.dcd = 1;
 				if (status & UART_MSR_DSR)
@@ -1575,13 +1534,11 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
 				if (status & UART_MSR_CTS)
 					ms.cts = 1;
 			copy:
-				if (copy_to_user(msu, &ms, sizeof(ms))) {
-					unlock_kernel();
+				mutex_unlock(&port->mutex);
+				if (copy_to_user(msu, &ms, sizeof(ms)))
 					return -EFAULT;
-				}
 				msu++;
 			}
-		unlock_kernel();
 		return 0;
 	}
 	case MOXA_ASPP_MON_EXT: {
@@ -1593,41 +1550,48 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
 		if (!me)
 			return -ENOMEM;
 
-		lock_kernel();
 		for (i = 0, p = 0; i < MXSER_BOARDS; i++) {
 			for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) {
 				if (p >= ARRAY_SIZE(me->rx_cnt)) {
 					i = MXSER_BOARDS;
 					break;
 				}
-				port = &mxser_boards[i].ports[j];
-				if (!port->ioaddr)
+				ip = &mxser_boards[i].ports[j];
+				port = &ip->port;
+
+				mutex_lock(&port->mutex);
+				if (!ip->ioaddr) {
+					mutex_unlock(&port->mutex);
 					continue;
+				}
 
-				status = mxser_get_msr(port->ioaddr, 0, p);
+				spin_lock_irq(&ip->slock);
+				status = mxser_get_msr(ip->ioaddr, 0, p);
 
 				if (status & UART_MSR_TERI)
-					port->icount.rng++;
+					ip->icount.rng++;
 				if (status & UART_MSR_DDSR)
-					port->icount.dsr++;
+					ip->icount.dsr++;
 				if (status & UART_MSR_DDCD)
-					port->icount.dcd++;
+					ip->icount.dcd++;
 				if (status & UART_MSR_DCTS)
-					port->icount.cts++;
+					ip->icount.cts++;
 
-				port->mon_data.modem_status = status;
-				me->rx_cnt[p] = port->mon_data.rxcnt;
-				me->tx_cnt[p] = port->mon_data.txcnt;
-				me->up_rxcnt[p] = port->mon_data.up_rxcnt;
-				me->up_txcnt[p] = port->mon_data.up_txcnt;
+				ip->mon_data.modem_status = status;
+				me->rx_cnt[p] = ip->mon_data.rxcnt;
+				me->tx_cnt[p] = ip->mon_data.txcnt;
+				me->up_rxcnt[p] = ip->mon_data.up_rxcnt;
+				me->up_txcnt[p] = ip->mon_data.up_txcnt;
 				me->modem_status[p] =
-					port->mon_data.modem_status;
-				tty = tty_port_tty_get(&port->port);
+					ip->mon_data.modem_status;
+				spin_unlock_irq(&ip->slock);
+
+				tty = tty_port_tty_get(&ip->port);
 
 				if (!tty || !tty->termios) {
-					cflag = port->normal_termios.c_cflag;
-					iflag = port->normal_termios.c_iflag;
-					me->baudrate[p] = tty_termios_baud_rate(&port->normal_termios);
+					cflag = ip->normal_termios.c_cflag;
+					iflag = ip->normal_termios.c_iflag;
+					me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios);
 				} else {
 					cflag = tty->termios->c_cflag;
 					iflag = tty->termios->c_iflag;
@@ -1646,16 +1610,15 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
 				if (iflag & (IXON | IXOFF))
 					me->flowctrl[p] |= 0x0C;
 
-				if (port->type == PORT_16550A)
+				if (ip->type == PORT_16550A)
 					me->fifo[p] = 1;
 
-				opmode = inb(port->opmode_ioaddr) >>
-						((p % 4) * 2);
+				opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2);
 				opmode &= OP_MODE_MASK;
 				me->iftype[p] = opmode;
+				mutex_unlock(&port->mutex);
 			}
 		}
-		unlock_kernel();
 		if (copy_to_user(argp, me, sizeof(*me)))
 			ret = -EFAULT;
 		kfree(me);
@@ -1692,6 +1655,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
 		unsigned int cmd, unsigned long arg)
 {
 	struct mxser_port *info = tty->driver_data;
+	struct tty_port *port = &info->port;
 	struct async_icount cnow;
 	unsigned long flags;
 	void __user *argp = (void __user *)arg;
@@ -1716,20 +1680,20 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
 					opmode != RS422_MODE &&
 					opmode != RS485_4WIRE_MODE)
 				return -EFAULT;
-			lock_kernel();
 			mask = ModeMask[p];
 			shiftbit = p * 2;
+			spin_lock_irq(&info->slock);
 			val = inb(info->opmode_ioaddr);
 			val &= mask;
 			val |= (opmode << shiftbit);
 			outb(val, info->opmode_ioaddr);
-			unlock_kernel();
+			spin_unlock_irq(&info->slock);
 		} else {
-			lock_kernel();
 			shiftbit = p * 2;
+			spin_lock_irq(&info->slock);
 			opmode = inb(info->opmode_ioaddr) >> shiftbit;
+			spin_unlock_irq(&info->slock);
 			opmode &= OP_MODE_MASK;
-			unlock_kernel();
 			if (put_user(opmode, (int __user *)argp))
 				return -EFAULT;
 		}
@@ -1742,14 +1706,14 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
 
 	switch (cmd) {
 	case TIOCGSERIAL:
-		lock_kernel();
+		mutex_lock(&port->mutex);
 		retval = mxser_get_serial_info(tty, argp);
-		unlock_kernel();
+		mutex_unlock(&port->mutex);
 		return retval;
 	case TIOCSSERIAL:
-		lock_kernel();
+		mutex_lock(&port->mutex);
 		retval = mxser_set_serial_info(tty, argp);
-		unlock_kernel();
+		mutex_unlock(&port->mutex);
 		return retval;
 	case TIOCSERGETLSR:	/* Get line status register */
 		return  mxser_get_lsr_info(info, argp);
@@ -1795,31 +1759,33 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
 	case MOXA_HighSpeedOn:
 		return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
 	case MOXA_SDS_RSTICOUNTER:
-		lock_kernel();
+		spin_lock_irq(&info->slock);
 		info->mon_data.rxcnt = 0;
 		info->mon_data.txcnt = 0;
-		unlock_kernel();
+		spin_unlock_irq(&info->slock);
 		return 0;
 
 	case MOXA_ASPP_OQUEUE:{
 		int len, lsr;
 
-		lock_kernel();
 		len = mxser_chars_in_buffer(tty);
+		spin_lock(&info->slock);
 		lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE;
+		spin_unlock_irq(&info->slock);
 		len += (lsr ? 0 : 1);
-		unlock_kernel();
 
 		return put_user(len, (int __user *)argp);
 	}
 	case MOXA_ASPP_MON: {
 		int mcr, status;
 
-		lock_kernel();
+		spin_lock(&info->slock);
 		status = mxser_get_msr(info->ioaddr, 1, tty->index);
 		mxser_check_modem_status(tty, info, status);
 
 		mcr = inb(info->ioaddr + UART_MCR);
+		spin_unlock(&info->slock);
+
 		if (mcr & MOXA_MUST_MCR_XON_FLAG)
 			info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD;
 		else
@@ -1834,7 +1800,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
 			info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD;
 		else
 			info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD;
-		unlock_kernel();
+
 		if (copy_to_user(argp, &info->mon_data,
 				sizeof(struct mxser_mon)))
 			return -EFAULT;
@@ -1993,6 +1959,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
 {
 	struct mxser_port *info = tty->driver_data;
 	unsigned long orig_jiffies, char_time;
+	unsigned long flags;
 	int lsr;
 
 	if (info->type == PORT_UNKNOWN)
@@ -2032,19 +1999,21 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
 		timeout, char_time);
 	printk("jiff=%lu...", jiffies);
 #endif
-	lock_kernel();
+	spin_lock_irqsave(&info->slock, flags);
 	while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) {
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
 		printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
 #endif
+		spin_unlock_irqrestore(&info->slock, flags);
 		schedule_timeout_interruptible(char_time);
+		spin_lock_irqsave(&info->slock, flags);
 		if (signal_pending(current))
 			break;
 		if (timeout && time_after(jiffies, orig_jiffies + timeout))
 			break;
 	}
+	spin_unlock_irqrestore(&info->slock, flags);
 	set_current_state(TASK_RUNNING);
-	unlock_kernel();
 
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
 	printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
@@ -2059,7 +2028,6 @@ static void mxser_hangup(struct tty_struct *tty)
 	struct mxser_port *info = tty->driver_data;
 
 	mxser_flush_buffer(tty);
-	mxser_shutdown(tty);
 	tty_port_hangup(&info->port);
 }
 
@@ -2363,6 +2331,8 @@ static const struct tty_operations mxser_ops = {
 struct tty_port_operations mxser_port_ops = {
 	.carrier_raised = mxser_carrier_raised,
 	.dtr_rts = mxser_dtr_rts,
+	.activate = mxser_activate,
+	.shutdown = mxser_shutdown_port,
 };
 
 /*
diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c
index 674b3ab3587d..2bb7874a6899 100644
--- a/drivers/char/pcmcia/ipwireless/tty.c
+++ b/drivers/char/pcmcia/ipwireless/tty.c
@@ -603,7 +603,7 @@ void ipwireless_tty_free(struct ipw_tty *tty)
 	}
 }
 
-static struct tty_operations tty_ops = {
+static const struct tty_operations tty_ops = {
 	.open = ipw_open,
 	.close = ipw_close,
 	.hangup = ipw_hangup,
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index d86c0bc05c1c..385c44b3034f 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -659,7 +659,7 @@ static int __ptmx_open(struct inode *inode, struct file *filp)
 	if (!retval)
 		return 0;
 out1:
-	tty_release_dev(filp);
+	tty_release(inode, filp);
 	return retval;
 out:
 	devpts_kill_index(inode, index);
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 3cfa22d469e0..0a8d1e56c993 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -793,26 +793,21 @@ static void rc_change_speed(struct tty_struct *tty, struct riscom_board *bp,
 }
 
 /* Must be called with interrupts enabled */
-static int rc_setup_port(struct tty_struct *tty, struct riscom_board *bp,
-						struct riscom_port *port)
+static int rc_activate_port(struct tty_port *port, struct tty_struct *tty)
 {
+	struct riscom_port *rp = container_of(port, struct riscom_port, port);
+	struct riscom_board *bp = port_Board(rp);
 	unsigned long flags;
 
-	if (port->port.flags & ASYNC_INITIALIZED)
-		return 0;
-
-	if (tty_port_alloc_xmit_buf(&port->port) < 0)
+	if (tty_port_alloc_xmit_buf(port) < 0)
 		return -ENOMEM;
 
 	spin_lock_irqsave(&riscom_lock, flags);
 
 	clear_bit(TTY_IO_ERROR, &tty->flags);
-	if (port->port.count == 1)
-		bp->count++;
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	rc_change_speed(tty, bp, port);
-	port->port.flags |= ASYNC_INITIALIZED;
-
+	bp->count++;
+	rp->xmit_cnt = rp->xmit_head = rp->xmit_tail = 0;
+	rc_change_speed(tty, bp, rp);
 	spin_unlock_irqrestore(&riscom_lock, flags);
 	return 0;
 }
@@ -821,9 +816,6 @@ static int rc_setup_port(struct tty_struct *tty, struct riscom_board *bp,
 static void rc_shutdown_port(struct tty_struct *tty,
 			struct riscom_board *bp, struct riscom_port *port)
 {
-	if (!(port->port.flags & ASYNC_INITIALIZED))
-		return;
-
 #ifdef RC_REPORT_OVERRUN
 	printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n",
 	       board_No(bp), port_No(port), port->overrun);
@@ -840,11 +832,6 @@ static void rc_shutdown_port(struct tty_struct *tty,
 	}
 #endif
 	tty_port_free_xmit_buf(&port->port);
-	if (C_HUPCL(tty)) {
-		/* Drop DTR */
-		bp->DTR |= (1u << port_No(port));
-		rc_out(bp, RC_DTR, bp->DTR);
-	}
 
 	/* Select port */
 	rc_out(bp, CD180_CAR, port_No(port));
@@ -856,7 +843,6 @@ static void rc_shutdown_port(struct tty_struct *tty,
 	rc_out(bp, CD180_IER, port->IER);
 
 	set_bit(TTY_IO_ERROR, &tty->flags);
-	port->port.flags &= ~ASYNC_INITIALIZED;
 
 	if (--bp->count < 0)  {
 		printk(KERN_INFO "rc%d: rc_shutdown_port: "
@@ -889,6 +875,20 @@ static int carrier_raised(struct tty_port *port)
 	return CD;
 }
 
+static void dtr_rts(struct tty_port *port, int onoff)
+{
+	struct riscom_port *p = container_of(port, struct riscom_port, port);
+	struct riscom_board *bp = port_Board(p);
+	unsigned long flags;
+
+	spin_lock_irqsave(&riscom_lock, flags);
+	bp->DTR &= ~(1u << port_No(p));
+	if (onoff == 0)
+		bp->DTR |= (1u << port_No(p));
+	rc_out(bp, RC_DTR, bp->DTR);
+	spin_unlock_irqrestore(&riscom_lock, flags);
+}
+
 static int rc_open(struct tty_struct *tty, struct file *filp)
 {
 	int board;
@@ -909,14 +909,7 @@ static int rc_open(struct tty_struct *tty, struct file *filp)
 	if (error)
 		return error;
 
-	port->port.count++;
-	tty->driver_data = port;
-	tty_port_tty_set(&port->port, tty);
-
-	error = rc_setup_port(tty, bp, port);
-	if (error == 0)
-		error = tty_port_block_til_ready(&port->port, tty, filp);
-	return error;
+	return tty_port_open(&port->port, tty, filp);
 }
 
 static void rc_flush_buffer(struct tty_struct *tty)
@@ -950,24 +943,23 @@ static void rc_close_port(struct tty_port *port)
 
 	spin_lock_irqsave(&riscom_lock, flags);
 	rp->IER &= ~IER_RXD;
-	if (port->flags & ASYNC_INITIALIZED) {
-		rp->IER &= ~IER_TXRDY;
-		rp->IER |= IER_TXEMPTY;
-		rc_out(bp, CD180_CAR, port_No(rp));
-		rc_out(bp, CD180_IER, rp->IER);
-		/*
-		 * Before we drop DTR, make sure the UART transmitter
-		 * has completely drained; this is especially
-		 * important if there is a transmit FIFO!
-		 */
-		timeout = jiffies + HZ;
-		while (rp->IER & IER_TXEMPTY) {
-			spin_unlock_irqrestore(&riscom_lock, flags);
-			msleep_interruptible(jiffies_to_msecs(rp->timeout));
-			spin_lock_irqsave(&riscom_lock, flags);
-			if (time_after(jiffies, timeout))
-				break;
-		}
+
+	rp->IER &= ~IER_TXRDY;
+	rp->IER |= IER_TXEMPTY;
+	rc_out(bp, CD180_CAR, port_No(rp));
+	rc_out(bp, CD180_IER, rp->IER);
+	/*
+	 * Before we drop DTR, make sure the UART transmitter
+	 * has completely drained; this is especially
+	 * important if there is a transmit FIFO!
+	 */
+	timeout = jiffies + HZ;
+	while (rp->IER & IER_TXEMPTY) {
+		spin_unlock_irqrestore(&riscom_lock, flags);
+		msleep_interruptible(jiffies_to_msecs(rp->timeout));
+		spin_lock_irqsave(&riscom_lock, flags);
+		if (time_after(jiffies, timeout))
+			break;
 	}
 	rc_shutdown_port(port->tty, bp, rp);
 	spin_unlock_irqrestore(&riscom_lock, flags);
@@ -1354,7 +1346,6 @@ static void rc_hangup(struct tty_struct *tty)
 	if (rc_paranoia_check(port, tty->name, "rc_hangup"))
 		return;
 
-	rc_shutdown_port(tty, port_Board(port), port);
 	tty_port_hangup(&port->port);
 }
 
@@ -1401,7 +1392,9 @@ static const struct tty_operations riscom_ops = {
 
 static const struct tty_port_operations riscom_port_ops = {
 	.carrier_raised = carrier_raised,
+	.dtr_rts = dtr_rts,
 	.shutdown = rc_close_port,
+	.activate = rc_activate_port,
 };
 
 
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index db6dcfa35ba0..0e511d61f544 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -407,7 +407,7 @@ static unsigned int	stl_baudrates[] = {
  *	Declare all those functions in this driver!
  */
 
-static int	stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
+static long	stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg);
 static int	stl_brdinit(struct stlbrd *brdp);
 static int	stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp);
 static int	stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
@@ -607,7 +607,7 @@ static unsigned int	sc26198_baudtable[] = {
  */
 static const struct file_operations	stl_fsiomem = {
 	.owner		= THIS_MODULE,
-	.ioctl		= stl_memioctl,
+	.unlocked_ioctl	= stl_memioctl,
 };
 
 static struct class *stallion_class;
@@ -702,6 +702,24 @@ static struct stlbrd *stl_allocbrd(void)
 
 /*****************************************************************************/
 
+static int stl_activate(struct tty_port *port, struct tty_struct *tty)
+{
+	struct stlport *portp = container_of(port, struct stlport, port);
+	if (!portp->tx.buf) {
+		portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
+		if (!portp->tx.buf)
+			return -ENOMEM;
+		portp->tx.head = portp->tx.buf;
+		portp->tx.tail = portp->tx.buf;
+	}
+	stl_setport(portp, tty->termios);
+	portp->sigs = stl_getsignals(portp);
+	stl_setsignals(portp, 1, 1);
+	stl_enablerxtx(portp, 1, 1);
+	stl_startrxtx(portp, 1, 0);
+	return 0;
+}
+
 static int stl_open(struct tty_struct *tty, struct file *filp)
 {
 	struct stlport	*portp;
@@ -737,32 +755,8 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
 	if (portp == NULL)
 		return -ENODEV;
 	port = &portp->port;
+	return tty_port_open(&portp->port, tty, filp);
 
-/*
- *	On the first open of the device setup the port hardware, and
- *	initialize the per port data structure.
- */
-	tty_port_tty_set(port, tty);
-	tty->driver_data = portp;
-	port->count++;
-
-	if ((port->flags & ASYNC_INITIALIZED) == 0) {
-		if (!portp->tx.buf) {
-			portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
-			if (!portp->tx.buf)
-				return -ENOMEM;
-			portp->tx.head = portp->tx.buf;
-			portp->tx.tail = portp->tx.buf;
-		}
-		stl_setport(portp, tty->termios);
-		portp->sigs = stl_getsignals(portp);
-		stl_setsignals(portp, 1, 1);
-		stl_enablerxtx(portp, 1, 1);
-		stl_startrxtx(portp, 1, 0);
-		clear_bit(TTY_IO_ERROR, &tty->flags);
-		port->flags |= ASYNC_INITIALIZED;
-	}
-	return tty_port_block_til_ready(port, tty, filp);
 }
 
 /*****************************************************************************/
@@ -826,38 +820,12 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
 
 /*****************************************************************************/
 
-static void stl_close(struct tty_struct *tty, struct file *filp)
+static void stl_shutdown(struct tty_port *port)
 {
-	struct stlport	*portp;
-	struct tty_port *port;
-	unsigned long	flags;
-
-	pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
-
-	portp = tty->driver_data;
-	BUG_ON(portp == NULL);
-
-	port = &portp->port;
-
-	if (tty_port_close_start(port, tty, filp) == 0)
-		return;
-/*
- *	May want to wait for any data to drain before closing. The BUSY
- *	flag keeps track of whether we are still sending or not - it is
- *	very accurate for the cd1400, not quite so for the sc26198.
- *	(The sc26198 has no "end-of-data" interrupt only empty FIFO)
- */
-	stl_waituntilsent(tty, (HZ / 2));
-
-	spin_lock_irqsave(&port->lock, flags);
-	portp->port.flags &= ~ASYNC_INITIALIZED;
-	spin_unlock_irqrestore(&port->lock, flags);
-
+	struct stlport *portp = container_of(port, struct stlport, port);
 	stl_disableintrs(portp);
-	if (tty->termios->c_cflag & HUPCL)
-		stl_setsignals(portp, 0, 0);
 	stl_enablerxtx(portp, 0, 0);
-	stl_flushbuffer(tty);
+	stl_flush(portp);
 	portp->istate = 0;
 	if (portp->tx.buf != NULL) {
 		kfree(portp->tx.buf);
@@ -865,9 +833,16 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
 		portp->tx.head = NULL;
 		portp->tx.tail = NULL;
 	}
+}
+
+static void stl_close(struct tty_struct *tty, struct file *filp)
+{
+	struct stlport*portp;
+	pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
 
-	tty_port_close_end(port, tty);
-	tty_port_tty_set(port, NULL);
+	portp = tty->driver_data;
+	BUG_ON(portp == NULL);
+	tty_port_close(&portp->port, tty, filp);
 }
 
 /*****************************************************************************/
@@ -1314,35 +1289,12 @@ static void stl_stop(struct tty_struct *tty)
 
 static void stl_hangup(struct tty_struct *tty)
 {
-	struct stlport	*portp;
-	struct tty_port *port;
-	unsigned long flags;
-
+	struct stlport	*portp = tty->driver_data;
 	pr_debug("stl_hangup(tty=%p)\n", tty);
 
-	portp = tty->driver_data;
 	if (portp == NULL)
 		return;
-	port = &portp->port;
-
-	spin_lock_irqsave(&port->lock, flags);
-	port->flags &= ~ASYNC_INITIALIZED;
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	stl_disableintrs(portp);
-	if (tty->termios->c_cflag & HUPCL)
-		stl_setsignals(portp, 0, 0);
-	stl_enablerxtx(portp, 0, 0);
-	stl_flushbuffer(tty);
-	portp->istate = 0;
-	set_bit(TTY_IO_ERROR, &tty->flags);
-	if (portp->tx.buf != NULL) {
-		kfree(portp->tx.buf);
-		portp->tx.buf = NULL;
-		portp->tx.head = NULL;
-		portp->tx.tail = NULL;
-	}
-	tty_port_hangup(port);
+	tty_port_hangup(&portp->port);
 }
 
 /*****************************************************************************/
@@ -2486,18 +2438,19 @@ static int stl_getbrdstruct(struct stlbrd __user *arg)
  *	collection.
  */
 
-static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
+static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
 {
 	int	brdnr, rc;
 	void __user *argp = (void __user *)arg;
 
-	pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
+	pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg);
 
-	brdnr = iminor(ip);
+	brdnr = iminor(fp->f_dentry->d_inode);
 	if (brdnr >= STL_MAXBRDS)
 		return -ENODEV;
 	rc = 0;
 
+	lock_kernel();
 	switch (cmd) {
 	case COM_GETPORTSTATS:
 		rc = stl_getportstats(NULL, NULL, argp);
@@ -2518,7 +2471,7 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns
 		rc = -ENOIOCTLCMD;
 		break;
 	}
-
+	unlock_kernel();
 	return rc;
 }
 
@@ -2549,6 +2502,8 @@ static const struct tty_operations stl_ops = {
 static const struct tty_port_operations stl_port_ops = {
 	.carrier_raised = stl_carrier_raised,
 	.dtr_rts = stl_dtr_rts,
+	.activate = stl_activate,
+	.shutdown = stl_shutdown,
 };
 
 /*****************************************************************************/
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 59499ee0fe6a..684f0e0b175e 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -142,7 +142,6 @@ ssize_t redirected_tty_write(struct file *, const char __user *,
 							size_t, loff_t *);
 static unsigned int tty_poll(struct file *, poll_table *);
 static int tty_open(struct inode *, struct file *);
-static int tty_release(struct inode *, struct file *);
 long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 #ifdef CONFIG_COMPAT
 static long tty_compat_ioctl(struct file *file, unsigned int cmd,
@@ -506,8 +505,6 @@ static void do_tty_hangup(struct work_struct *work)
 	if (!tty)
 		return;
 
-	/* inuse_filps is protected by the single kernel lock */
-	lock_kernel();
 
 	spin_lock(&redirect_lock);
 	if (redirect && redirect->private_data == tty) {
@@ -516,7 +513,11 @@ static void do_tty_hangup(struct work_struct *work)
 	}
 	spin_unlock(&redirect_lock);
 
+	/* inuse_filps is protected by the single kernel lock */
+	lock_kernel();
 	check_tty_count(tty, "do_tty_hangup");
+	unlock_kernel();
+
 	file_list_lock();
 	/* This breaks for file handles being sent over AF_UNIX sockets ? */
 	list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) {
@@ -530,6 +531,7 @@ static void do_tty_hangup(struct work_struct *work)
 	}
 	file_list_unlock();
 
+	lock_kernel();
 	tty_ldisc_hangup(tty);
 
 	read_lock(&tasklist_lock);
@@ -708,6 +710,8 @@ void disassociate_ctty(int on_exit)
 	struct tty_struct *tty;
 	struct pid *tty_pgrp = NULL;
 
+	if (!current->signal->leader)
+		return;
 
 	tty = get_current_tty();
 	if (tty) {
@@ -773,8 +777,7 @@ void no_tty(void)
 {
 	struct task_struct *tsk = current;
 	lock_kernel();
-	if (tsk->signal->leader)
-		disassociate_ctty(0);
+	disassociate_ctty(0);
 	unlock_kernel();
 	proc_clear_tty(tsk);
 }
@@ -1017,14 +1020,16 @@ out:
 
 void tty_write_message(struct tty_struct *tty, char *msg)
 {
-	lock_kernel();
 	if (tty) {
 		mutex_lock(&tty->atomic_write_lock);
-		if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags))
+		lock_kernel();
+		if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) {
+			unlock_kernel();
 			tty->ops->write(tty, msg, strlen(msg));
+		} else
+			unlock_kernel();
 		tty_write_unlock(tty);
 	}
-	unlock_kernel();
 	return;
 }
 
@@ -1202,14 +1207,21 @@ static int tty_driver_install_tty(struct tty_driver *driver,
 						struct tty_struct *tty)
 {
 	int idx = tty->index;
+	int ret;
 
-	if (driver->ops->install)
-		return driver->ops->install(driver, tty);
+	if (driver->ops->install) {
+		lock_kernel();
+		ret = driver->ops->install(driver, tty);
+		unlock_kernel();
+		return ret;
+	}
 
 	if (tty_init_termios(tty) == 0) {
+		lock_kernel();
 		tty_driver_kref_get(driver);
 		tty->count++;
 		driver->ttys[idx] = tty;
+		unlock_kernel();
 		return 0;
 	}
 	return -ENOMEM;
@@ -1302,10 +1314,14 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
 	struct tty_struct *tty;
 	int retval;
 
+	lock_kernel();
 	/* Check if pty master is being opened multiple times */
 	if (driver->subtype == PTY_TYPE_MASTER &&
-		(driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok)
+		(driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) {
+		unlock_kernel();
 		return ERR_PTR(-EIO);
+	}
+	unlock_kernel();
 
 	/*
 	 * First time open is complex, especially for PTY devices.
@@ -1335,7 +1351,6 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
 	 * If we fail here just call release_tty to clean up.  No need
 	 * to decrement the use counts, as release_tty doesn't care.
 	 */
-
 	retval = tty_ldisc_setup(tty, tty->link);
 	if (retval)
 		goto release_mem_out;
@@ -1350,7 +1365,9 @@ release_mem_out:
 	if (printk_ratelimit())
 		printk(KERN_INFO "tty_init_dev: ldisc open failed, "
 				 "clearing slot %d\n", idx);
+	lock_kernel();
 	release_tty(tty, idx);
+	unlock_kernel();
 	return ERR_PTR(retval);
 }
 
@@ -1464,7 +1481,17 @@ static void release_tty(struct tty_struct *tty, int idx)
 	tty_kref_put(tty);
 }
 
-/*
+/**
+ *	tty_release		-	vfs callback for close
+ *	@inode: inode of tty
+ *	@filp: file pointer for handle to tty
+ *
+ *	Called the last time each file handle is closed that references
+ *	this tty. There may however be several such references.
+ *
+ *	Locking:
+ *		Takes bkl. See tty_release_dev
+ *
  * Even releasing the tty structures is a tricky business.. We have
  * to be very careful that the structures are all released at the
  * same time, as interrupts might otherwise get the wrong pointers.
@@ -1472,20 +1499,20 @@ static void release_tty(struct tty_struct *tty, int idx)
  * WSH 09/09/97: rewritten to avoid some nasty race conditions that could
  * lead to double frees or releasing memory still in use.
  */
-void tty_release_dev(struct file *filp)
+
+int tty_release(struct inode *inode, struct file *filp)
 {
 	struct tty_struct *tty, *o_tty;
 	int	pty_master, tty_closing, o_tty_closing, do_sleep;
 	int	devpts;
 	int	idx;
 	char	buf[64];
-	struct 	inode *inode;
 
-	inode = filp->f_path.dentry->d_inode;
 	tty = (struct tty_struct *)filp->private_data;
 	if (tty_paranoia_check(tty, inode, "tty_release_dev"))
-		return;
+		return 0;
 
+	lock_kernel();
 	check_tty_count(tty, "tty_release_dev");
 
 	tty_fasync(-1, filp, 0);
@@ -1500,19 +1527,22 @@ void tty_release_dev(struct file *filp)
 	if (idx < 0 || idx >= tty->driver->num) {
 		printk(KERN_DEBUG "tty_release_dev: bad idx when trying to "
 				  "free (%s)\n", tty->name);
-		return;
+		unlock_kernel();
+		return 0;
 	}
 	if (!devpts) {
 		if (tty != tty->driver->ttys[idx]) {
+			unlock_kernel();
 			printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty "
 			       "for (%s)\n", idx, tty->name);
-			return;
+			return 0;
 		}
 		if (tty->termios != tty->driver->termios[idx]) {
+			unlock_kernel();
 			printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios "
 			       "for (%s)\n",
 			       idx, tty->name);
-			return;
+			return 0;
 		}
 	}
 #endif
@@ -1526,26 +1556,30 @@ void tty_release_dev(struct file *filp)
 	if (tty->driver->other &&
 	     !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
 		if (o_tty != tty->driver->other->ttys[idx]) {
+			unlock_kernel();
 			printk(KERN_DEBUG "tty_release_dev: other->table[%d] "
 					  "not o_tty for (%s)\n",
 			       idx, tty->name);
-			return;
+			return 0 ;
 		}
 		if (o_tty->termios != tty->driver->other->termios[idx]) {
+			unlock_kernel();
 			printk(KERN_DEBUG "tty_release_dev: other->termios[%d] "
 					  "not o_termios for (%s)\n",
 			       idx, tty->name);
-			return;
+			return 0;
 		}
 		if (o_tty->link != tty) {
+			unlock_kernel();
 			printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n");
-			return;
+			return 0;
 		}
 	}
 #endif
 	if (tty->ops->close)
 		tty->ops->close(tty, filp);
 
+	unlock_kernel();
 	/*
 	 * 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
@@ -1568,6 +1602,7 @@ void tty_release_dev(struct file *filp)
 		   opens on /dev/tty */
 
 		mutex_lock(&tty_mutex);
+		lock_kernel();
 		tty_closing = tty->count <= 1;
 		o_tty_closing = o_tty &&
 			(o_tty->count <= (pty_master ? 1 : 0));
@@ -1598,6 +1633,7 @@ void tty_release_dev(struct file *filp)
 
 		printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue "
 				    "active!\n", tty_name(tty, buf));
+		unlock_kernel();
 		mutex_unlock(&tty_mutex);
 		schedule();
 	}
@@ -1661,8 +1697,10 @@ void tty_release_dev(struct file *filp)
 	mutex_unlock(&tty_mutex);
 
 	/* check whether both sides are closing ... */
-	if (!tty_closing || (o_tty && !o_tty_closing))
-		return;
+	if (!tty_closing || (o_tty && !o_tty_closing)) {
+		unlock_kernel();
+		return 0;
+	}
 
 #ifdef TTY_DEBUG_HANGUP
 	printk(KERN_DEBUG "freeing tty structure...");
@@ -1680,10 +1718,12 @@ void tty_release_dev(struct file *filp)
 	/* Make this pty number available for reallocation */
 	if (devpts)
 		devpts_kill_index(inode, idx);
+	unlock_kernel();
+	return 0;
 }
 
 /**
- *	__tty_open		-	open a tty device
+ *	tty_open		-	open a tty device
  *	@inode: inode of device file
  *	@filp: file pointer to tty
  *
@@ -1703,7 +1743,7 @@ void tty_release_dev(struct file *filp)
  *		 ->siglock protects ->signal/->sighand
  */
 
-static int __tty_open(struct inode *inode, struct file *filp)
+static int tty_open(struct inode *inode, struct file *filp)
 {
 	struct tty_struct *tty = NULL;
 	int noctty, retval;
@@ -1720,10 +1760,12 @@ retry_open:
 	retval = 0;
 
 	mutex_lock(&tty_mutex);
+	lock_kernel();
 
 	if (device == MKDEV(TTYAUX_MAJOR, 0)) {
 		tty = get_current_tty();
 		if (!tty) {
+			unlock_kernel();
 			mutex_unlock(&tty_mutex);
 			return -ENXIO;
 		}
@@ -1755,12 +1797,14 @@ retry_open:
 				goto got_driver;
 			}
 		}
+		unlock_kernel();
 		mutex_unlock(&tty_mutex);
 		return -ENODEV;
 	}
 
 	driver = get_tty_driver(device, &index);
 	if (!driver) {
+		unlock_kernel();
 		mutex_unlock(&tty_mutex);
 		return -ENODEV;
 	}
@@ -1770,6 +1814,7 @@ got_driver:
 		tty = tty_driver_lookup_tty(driver, inode, index);
 
 		if (IS_ERR(tty)) {
+			unlock_kernel();
 			mutex_unlock(&tty_mutex);
 			return PTR_ERR(tty);
 		}
@@ -1784,8 +1829,10 @@ got_driver:
 
 	mutex_unlock(&tty_mutex);
 	tty_driver_kref_put(driver);
-	if (IS_ERR(tty))
+	if (IS_ERR(tty)) {
+		unlock_kernel();
 		return PTR_ERR(tty);
+	}
 
 	filp->private_data = tty;
 	file_move(filp, &tty->tty_files);
@@ -1813,11 +1860,15 @@ got_driver:
 		printk(KERN_DEBUG "error %d in opening %s...", retval,
 		       tty->name);
 #endif
-		tty_release_dev(filp);
-		if (retval != -ERESTARTSYS)
+		tty_release(inode, filp);
+		if (retval != -ERESTARTSYS) {
+			unlock_kernel();
 			return retval;
-		if (signal_pending(current))
+		}
+		if (signal_pending(current)) {
+			unlock_kernel();
 			return retval;
+		}
 		schedule();
 		/*
 		 * Need to reset f_op in case a hangup happened.
@@ -1826,8 +1877,11 @@ got_driver:
 			filp->f_op = &tty_fops;
 		goto retry_open;
 	}
+	unlock_kernel();
+
 
 	mutex_lock(&tty_mutex);
+	lock_kernel();
 	spin_lock_irq(&current->sighand->siglock);
 	if (!noctty &&
 	    current->signal->leader &&
@@ -1835,43 +1889,12 @@ got_driver:
 	    tty->session == NULL)
 		__proc_set_tty(current, tty);
 	spin_unlock_irq(&current->sighand->siglock);
+	unlock_kernel();
 	mutex_unlock(&tty_mutex);
 	return 0;
 }
 
-/* BKL pushdown: scary code avoidance wrapper */
-static int tty_open(struct inode *inode, struct file *filp)
-{
-	int ret;
-
-	lock_kernel();
-	ret = __tty_open(inode, filp);
-	unlock_kernel();
-	return ret;
-}
-
-
-
-
-/**
- *	tty_release		-	vfs callback for close
- *	@inode: inode of tty
- *	@filp: file pointer for handle to tty
- *
- *	Called the last time each file handle is closed that references
- *	this tty. There may however be several such references.
- *
- *	Locking:
- *		Takes bkl. See tty_release_dev
- */
 
-static int tty_release(struct inode *inode, struct file *filp)
-{
-	lock_kernel();
-	tty_release_dev(filp);
-	unlock_kernel();
-	return 0;
-}
 
 /**
  *	tty_poll	-	check tty status
@@ -2317,9 +2340,7 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
 	if (get_user(ldisc, p))
 		return -EFAULT;
 
-	lock_kernel();
 	ret = tty_set_ldisc(tty, ldisc);
-	unlock_kernel();
 
 	return ret;
 }
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
index feb55075819b..3f653f7d849f 100644
--- a/drivers/char/tty_ldisc.c
+++ b/drivers/char/tty_ldisc.c
@@ -34,6 +34,8 @@
 #include <linux/vt_kern.h>
 #include <linux/selection.h>
 
+#include <linux/smp_lock.h>	/* For the moment */
+
 #include <linux/kmod.h>
 #include <linux/nsproxy.h>
 
@@ -443,8 +445,14 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
 static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
 {
 	WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags));
-	if (ld->ops->open)
-		return ld->ops->open(tty);
+	if (ld->ops->open) {
+		int ret;
+                /* BKL here locks verus a hangup event */
+		lock_kernel();
+		ret = ld->ops->open(tty);
+		unlock_kernel();
+		return ret;
+	}
 	return 0;
 }
 
@@ -545,6 +553,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 	if (IS_ERR(new_ldisc))
 		return PTR_ERR(new_ldisc);
 
+	lock_kernel();
 	/*
 	 *	We need to look at the tty locking here for pty/tty pairs
 	 *	when both sides try to change in parallel.
@@ -558,10 +567,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 	 */
 
 	if (tty->ldisc->ops->num == ldisc) {
+		unlock_kernel();
 		tty_ldisc_put(new_ldisc);
 		return 0;
 	}
 
+	unlock_kernel();
 	/*
 	 *	Problem: What do we do if this blocks ?
 	 *	We could deadlock here
@@ -582,6 +593,9 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 			test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0);
 		mutex_lock(&tty->ldisc_mutex);
 	}
+
+	lock_kernel();
+
 	set_bit(TTY_LDISC_CHANGING, &tty->flags);
 
 	/*
@@ -592,6 +606,8 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 	tty->receive_room = 0;
 
 	o_ldisc = tty->ldisc;
+
+	unlock_kernel();
 	/*
 	 *	Make sure we don't change while someone holds a
 	 *	reference to the line discipline. The TTY_LDISC bit
@@ -617,12 +633,14 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 	flush_scheduled_work();
 
 	mutex_lock(&tty->ldisc_mutex);
+	lock_kernel();
 	if (test_bit(TTY_HUPPED, &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);
+		unlock_kernel();
 		return -EIO;
 	}
 
@@ -664,6 +682,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 	if (o_work)
 		schedule_delayed_work(&o_tty->buf.work, 1);
 	mutex_unlock(&tty->ldisc_mutex);
+	unlock_kernel();
 	return retval;
 }
 
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
index c63f3d33914a..be492dd66437 100644
--- a/drivers/char/tty_port.c
+++ b/drivers/char/tty_port.c
@@ -25,19 +25,21 @@ void tty_port_init(struct tty_port *port)
 	init_waitqueue_head(&port->close_wait);
 	init_waitqueue_head(&port->delta_msr_wait);
 	mutex_init(&port->mutex);
+	mutex_init(&port->buf_mutex);
 	spin_lock_init(&port->lock);
 	port->close_delay = (50 * HZ) / 100;
 	port->closing_wait = (3000 * HZ) / 100;
+	kref_init(&port->kref);
 }
 EXPORT_SYMBOL(tty_port_init);
 
 int tty_port_alloc_xmit_buf(struct tty_port *port)
 {
 	/* We may sleep in get_zeroed_page() */
-	mutex_lock(&port->mutex);
+	mutex_lock(&port->buf_mutex);
 	if (port->xmit_buf == NULL)
 		port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
-	mutex_unlock(&port->mutex);
+	mutex_unlock(&port->buf_mutex);
 	if (port->xmit_buf == NULL)
 		return -ENOMEM;
 	return 0;
@@ -46,15 +48,32 @@ EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
 
 void tty_port_free_xmit_buf(struct tty_port *port)
 {
-	mutex_lock(&port->mutex);
+	mutex_lock(&port->buf_mutex);
 	if (port->xmit_buf != NULL) {
 		free_page((unsigned long)port->xmit_buf);
 		port->xmit_buf = NULL;
 	}
-	mutex_unlock(&port->mutex);
+	mutex_unlock(&port->buf_mutex);
 }
 EXPORT_SYMBOL(tty_port_free_xmit_buf);
 
+static void tty_port_destructor(struct kref *kref)
+{
+	struct tty_port *port = container_of(kref, struct tty_port, kref);
+	if (port->xmit_buf)
+		free_page((unsigned long)port->xmit_buf);
+	if (port->ops->destruct)
+		port->ops->destruct(port);
+	else
+		kfree(port);
+}
+
+void tty_port_put(struct tty_port *port)
+{
+	if (port)
+		kref_put(&port->kref, tty_port_destructor);
+}
+EXPORT_SYMBOL(tty_port_put);
 
 /**
  *	tty_port_tty_get	-	get a tty reference
@@ -99,10 +118,11 @@ EXPORT_SYMBOL(tty_port_tty_set);
 
 static void tty_port_shutdown(struct tty_port *port)
 {
+	mutex_lock(&port->mutex);
 	if (port->ops->shutdown &&
 		test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
 			port->ops->shutdown(port);
-
+	mutex_unlock(&port->mutex);
 }
 
 /**
@@ -120,8 +140,10 @@ void tty_port_hangup(struct tty_port *port)
 	spin_lock_irqsave(&port->lock, flags);
 	port->count = 0;
 	port->flags &= ~ASYNC_NORMAL_ACTIVE;
-	if (port->tty)
+	if (port->tty) {
+		set_bit(TTY_IO_ERROR, &port->tty->flags);
 		tty_kref_put(port->tty);
+	}
 	port->tty = NULL;
 	spin_unlock_irqrestore(&port->lock, flags);
 	wake_up_interruptible(&port->open_wait);
@@ -198,7 +220,7 @@ EXPORT_SYMBOL(tty_port_lower_dtr_rts);
  *	management of these lines. Note that the dtr/rts raise is done each
  *	iteration as a hangup may have previously dropped them while we wait.
  */
- 
+
 int tty_port_block_til_ready(struct tty_port *port,
 				struct tty_struct *tty, struct file *filp)
 {
@@ -253,7 +275,8 @@ int tty_port_block_til_ready(struct tty_port *port,
 			tty_port_raise_dtr_rts(port);
 
 		prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
-		/* Check for a hangup or uninitialised port. Return accordingly */
+		/* Check for a hangup or uninitialised port.
+							Return accordingly */
 		if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
 			if (port->flags & ASYNC_HUP_NOTIFY)
 				retval = -EAGAIN;
@@ -285,11 +308,11 @@ int tty_port_block_til_ready(struct tty_port *port,
 		port->flags |= ASYNC_NORMAL_ACTIVE;
 	spin_unlock_irqrestore(&port->lock, flags);
 	return retval;
-	
 }
 EXPORT_SYMBOL(tty_port_block_til_ready);
 
-int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp)
+int tty_port_close_start(struct tty_port *port,
+				struct tty_struct *tty, struct file *filp)
 {
 	unsigned long flags;
 
@@ -299,7 +322,7 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f
 		return 0;
 	}
 
-	if( tty->count == 1 && port->count != 1) {
+	if (tty->count == 1 && port->count != 1) {
 		printk(KERN_WARNING
 		    "tty_port_close_start: tty->count = 1 port count = %d.\n",
 								port->count);
@@ -331,12 +354,20 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f
 		long timeout;
 
 		if (bps > 1200)
-			timeout = max_t(long, (HZ * 10 * port->drain_delay) / bps,
-								HZ / 10);
+			timeout = max_t(long,
+				(HZ * 10 * port->drain_delay) / bps, HZ / 10);
 		else
 			timeout = 2 * HZ;
 		schedule_timeout_interruptible(timeout);
 	}
+	/* Flush the ldisc buffering */
+	tty_ldisc_flush(tty);
+
+	/* Drop DTR/RTS if HUPCL is set. This causes any attached modem to
+	   hang up the line */
+	if (tty->termios->c_cflag & HUPCL)
+		tty_port_lower_dtr_rts(port);
+
 	/* Don't call port->drop for the last reference. Callers will want
 	   to drop the last active reference in ->shutdown() or the tty
 	   shutdown path */
@@ -348,11 +379,6 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
 {
 	unsigned long flags;
 
-	tty_ldisc_flush(tty);
-
-	if (tty->termios->c_cflag & HUPCL)
-		tty_port_lower_dtr_rts(port);
-
 	spin_lock_irqsave(&port->lock, flags);
 	tty->closing = 0;
 
@@ -377,7 +403,42 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty,
 	if (tty_port_close_start(port, tty, filp) == 0)
 		return;
 	tty_port_shutdown(port);
+	set_bit(TTY_IO_ERROR, &tty->flags);
 	tty_port_close_end(port, tty);
 	tty_port_tty_set(port, NULL);
 }
 EXPORT_SYMBOL(tty_port_close);
+
+int tty_port_open(struct tty_port *port, struct tty_struct *tty,
+							struct file *filp)
+{
+	spin_lock_irq(&port->lock);
+	if (!tty_hung_up_p(filp))
+		++port->count;
+	spin_unlock_irq(&port->lock);
+	tty_port_tty_set(port, tty);
+
+	/*
+	 * Do the device-specific open only if the hardware isn't
+	 * already initialized. Serialize open and shutdown using the
+	 * port mutex.
+	 */
+
+	mutex_lock(&port->mutex);
+
+	if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
+		clear_bit(TTY_IO_ERROR, &tty->flags);
+		if (port->ops->activate) {
+			int retval = port->ops->activate(port, tty);
+			if (retval) {
+				mutex_unlock(&port->mutex);
+				return retval;
+			}
+		}
+		set_bit(ASYNCB_INITIALIZED, &port->flags);
+	}
+	mutex_unlock(&port->mutex);
+	return tty_port_block_til_ready(port, tty, filp);
+}
+
+EXPORT_SYMBOL(tty_port_open);
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index b8e7c5ae981e..f53755533e7e 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -29,6 +29,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/mutex.h>
 #include <linux/seq_file.h>
 #include <linux/serial_reg.h>
@@ -73,11 +74,10 @@ struct uart_icount {
 };
 
 struct sdio_uart_port {
+	struct tty_port		port;
 	struct kref		kref;
 	struct tty_struct	*tty;
 	unsigned int		index;
-	unsigned int		opened;
-	struct mutex		open_lock;
 	struct sdio_func	*func;
 	struct mutex		func_lock;
 	struct task_struct	*in_sdio_uart_irq;
@@ -87,6 +87,7 @@ struct sdio_uart_port {
 	struct uart_icount	icount;
 	unsigned int		uartclk;
 	unsigned int		mctrl;
+	unsigned int		rx_mctrl;
 	unsigned int		read_status_mask;
 	unsigned int		ignore_status_mask;
 	unsigned char		x_char;
@@ -102,7 +103,6 @@ static int sdio_uart_add_port(struct sdio_uart_port *port)
 	int index, ret = -EBUSY;
 
 	kref_init(&port->kref);
-	mutex_init(&port->open_lock);
 	mutex_init(&port->func_lock);
 	spin_lock_init(&port->write_lock);
 
@@ -151,6 +151,7 @@ static void sdio_uart_port_put(struct sdio_uart_port *port)
 static void sdio_uart_port_remove(struct sdio_uart_port *port)
 {
 	struct sdio_func *func;
+	struct tty_struct *tty;
 
 	BUG_ON(sdio_uart_table[port->index] != port);
 
@@ -165,15 +166,19 @@ static void sdio_uart_port_remove(struct sdio_uart_port *port)
 	 * give up on that port ASAP.
 	 * Beware: the lock ordering is critical.
 	 */
-	mutex_lock(&port->open_lock);
+	mutex_lock(&port->port.mutex);
 	mutex_lock(&port->func_lock);
 	func = port->func;
 	sdio_claim_host(func);
 	port->func = NULL;
 	mutex_unlock(&port->func_lock);
-	if (port->opened)
-		tty_hangup(port->tty);
-	mutex_unlock(&port->open_lock);
+	tty = tty_port_tty_get(&port->port);
+	/* tty_hangup is async so is this safe as is ?? */
+	if (tty) {
+		tty_hangup(tty);
+		tty_kref_put(tty);
+	}
+	mutex_unlock(&port->port.mutex);
 	sdio_release_irq(func);
 	sdio_disable_func(func);
 	sdio_release_host(func);
@@ -217,6 +222,8 @@ static unsigned int sdio_uart_get_mctrl(struct sdio_uart_port *port)
 	unsigned char status;
 	unsigned int ret;
 
+	/* FIXME: What stops this losing the delta bits and breaking
+	   sdio_uart_check_modem_status ? */
 	status = sdio_in(port, UART_MSR);
 
 	ret = 0;
@@ -391,7 +398,7 @@ static void sdio_uart_stop_rx(struct sdio_uart_port *port)
 static void sdio_uart_receive_chars(struct sdio_uart_port *port,
 				    unsigned int *status)
 {
-	struct tty_struct *tty = port->tty;
+	struct tty_struct *tty = tty_port_tty_get(&port->port);
 	unsigned int ch, flag;
 	int max_count = 256;
 
@@ -428,24 +435,30 @@ static void sdio_uart_receive_chars(struct sdio_uart_port *port,
 		}
 
 		if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0)
-			tty_insert_flip_char(tty, ch, flag);
+			if (tty)
+				tty_insert_flip_char(tty, ch, flag);
 
 		/*
 		 * Overrun is special.  Since it's reported immediately,
 		 * it doesn't affect the current character.
 		 */
 		if (*status & ~port->ignore_status_mask & UART_LSR_OE)
-			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+			if (tty)
+				tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 
 		*status = sdio_in(port, UART_LSR);
 	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(tty);
+	if (tty) {
+		tty_flip_buffer_push(tty);
+		tty_kref_put(tty);
+	}
 }
 
 static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
 {
 	struct circ_buf *xmit = &port->xmit;
 	int count;
+	struct tty_struct *tty;
 
 	if (port->x_char) {
 		sdio_out(port, UART_TX, port->x_char);
@@ -453,8 +466,13 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
 		port->x_char = 0;
 		return;
 	}
-	if (circ_empty(xmit) || port->tty->stopped || port->tty->hw_stopped) {
+
+	tty = tty_port_tty_get(&port->port);
+
+	if (tty == NULL || circ_empty(xmit) ||
+				tty->stopped || tty->hw_stopped) {
 		sdio_uart_stop_tx(port);
+		tty_kref_put(tty);
 		return;
 	}
 
@@ -468,15 +486,17 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
 	} while (--count > 0);
 
 	if (circ_chars_pending(xmit) < WAKEUP_CHARS)
-		tty_wakeup(port->tty);
+		tty_wakeup(tty);
 
 	if (circ_empty(xmit))
 		sdio_uart_stop_tx(port);
+	tty_kref_put(tty);
 }
 
 static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
 {
 	int status;
+	struct tty_struct *tty;
 
 	status = sdio_in(port, UART_MSR);
 
@@ -487,25 +507,39 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
 		port->icount.rng++;
 	if (status & UART_MSR_DDSR)
 		port->icount.dsr++;
-	if (status & UART_MSR_DDCD)
+	if (status & UART_MSR_DDCD) {
 		port->icount.dcd++;
+		/* DCD raise - wake for open */
+		if (status & UART_MSR_DCD)
+			wake_up_interruptible(&port->port.open_wait);
+		else {
+			/* DCD drop - hang up if tty attached */
+			tty = tty_port_tty_get(&port->port);
+			if (tty) {
+				tty_hangup(tty);
+				tty_kref_put(tty);
+			}
+		}
+	}
 	if (status & UART_MSR_DCTS) {
 		port->icount.cts++;
-		if (port->tty->termios->c_cflag & CRTSCTS) {
+		tty = tty_port_tty_get(&port->port);
+		if (tty && (tty->termios->c_cflag & CRTSCTS)) {
 			int cts = (status & UART_MSR_CTS);
-			if (port->tty->hw_stopped) {
+			if (tty->hw_stopped) {
 				if (cts) {
-					port->tty->hw_stopped = 0;
+					tty->hw_stopped = 0;
 					sdio_uart_start_tx(port);
-					tty_wakeup(port->tty);
+					tty_wakeup(tty);
 				}
 			} else {
 				if (!cts) {
-					port->tty->hw_stopped = 1;
+					tty->hw_stopped = 1;
 					sdio_uart_stop_tx(port);
 				}
 			}
 		}
+		tty_kref_put(tty);
 	}
 }
 
@@ -542,8 +576,62 @@ static void sdio_uart_irq(struct sdio_func *func)
 	port->in_sdio_uart_irq = NULL;
 }
 
-static int sdio_uart_startup(struct sdio_uart_port *port)
+static int uart_carrier_raised(struct tty_port *tport)
+{
+	struct sdio_uart_port *port =
+			container_of(tport, struct sdio_uart_port, port);
+	unsigned int ret = sdio_uart_claim_func(port);
+	if (ret)	/* Missing hardware shoudn't block for carrier */
+		return 1;
+	ret = sdio_uart_get_mctrl(port);
+	sdio_uart_release_func(port);
+	if (ret & TIOCM_CAR)
+		return 1;
+	return 0;
+}
+
+/**
+ *	uart_dtr_rts		-	 port helper to set uart signals
+ *	@tport: tty port to be updated
+ *	@onoff: set to turn on DTR/RTS
+ *
+ *	Called by the tty port helpers when the modem signals need to be
+ *	adjusted during an open, close and hangup.
+ */
+
+static void uart_dtr_rts(struct tty_port *tport, int onoff)
+{
+	struct sdio_uart_port *port =
+			container_of(tport, struct sdio_uart_port, port);
+	int ret = sdio_uart_claim_func(port);
+	if (ret)
+		return;
+	if (onoff == 0)
+		sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+	else
+		sdio_uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+	sdio_uart_release_func(port);
+}
+
+/**
+ *	sdio_uart_activate	-	start up hardware
+ *	@tport: tty port to activate
+ *	@tty: tty bound to this port
+ *
+ *	Activate a tty port. The port locking guarantees us this will be
+ *	run exactly once per set of opens, and if successful will see the
+ *	shutdown method run exactly once to match. Start up and shutdown are
+ *	protected from each other by the internal locking and will not run
+ *	at the same time even during a hangup event.
+ *
+ *	If we successfully start up the port we take an extra kref as we
+ *	will keep it around until shutdown when the kref is dropped.
+ */
+
+static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty)
 {
+	struct sdio_uart_port *port =
+			container_of(tport, struct sdio_uart_port, port);
 	unsigned long page;
 	int ret;
 
@@ -551,7 +639,7 @@ static int sdio_uart_startup(struct sdio_uart_port *port)
 	 * Set the TTY IO error marker - we will only clear this
 	 * once we have successfully opened the port.
 	 */
-	set_bit(TTY_IO_ERROR, &port->tty->flags);
+	set_bit(TTY_IO_ERROR, &tty->flags);
 
 	/* Initialise and allocate the transmit buffer. */
 	page = __get_free_page(GFP_KERNEL);
@@ -592,19 +680,19 @@ static int sdio_uart_startup(struct sdio_uart_port *port)
 	 */
 	sdio_out(port, UART_LCR, UART_LCR_WLEN8);
 
-	port->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
+	port->ier = UART_IER_RLSI|UART_IER_RDI|UART_IER_RTOIE|UART_IER_UUE;
 	port->mctrl = TIOCM_OUT2;
 
-	sdio_uart_change_speed(port, port->tty->termios, NULL);
+	sdio_uart_change_speed(port, tty->termios, NULL);
 
-	if (port->tty->termios->c_cflag & CBAUD)
+	if (tty->termios->c_cflag & CBAUD)
 		sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);
 
-	if (port->tty->termios->c_cflag & CRTSCTS)
+	if (tty->termios->c_cflag & CRTSCTS)
 		if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS))
-			port->tty->hw_stopped = 1;
+			tty->hw_stopped = 1;
 
-	clear_bit(TTY_IO_ERROR, &port->tty->flags);
+	clear_bit(TTY_IO_ERROR, &tty->flags);
 
 	/* Kick the IRQ handler once while we're still holding the host lock */
 	sdio_uart_irq(port->func);
@@ -621,8 +709,20 @@ err1:
 	return ret;
 }
 
-static void sdio_uart_shutdown(struct sdio_uart_port *port)
+/**
+ *	sdio_uart_shutdown	-	stop hardware
+ *	@tport: tty port to shut down
+ *
+ *	Deactivate a tty port. The port locking guarantees us this will be
+ *	run only if a successful matching activate already ran. The two are
+ *	protected from each other by the internal locking and will not run
+ *	at the same time even during a hangup event.
+ */
+
+static void sdio_uart_shutdown(struct tty_port *tport)
 {
+	struct sdio_uart_port *port =
+			container_of(tport, struct sdio_uart_port, port);
 	int ret;
 
 	ret = sdio_uart_claim_func(port);
@@ -631,12 +731,6 @@ static void sdio_uart_shutdown(struct sdio_uart_port *port)
 
 	sdio_uart_stop_rx(port);
 
-	/* TODO: wait here for TX FIFO to drain */
-
-	/* Turn off DTR and RTS early. */
-	if (port->tty->termios->c_cflag & HUPCL)
-		sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-
 	/* Disable interrupts from this port */
 	sdio_release_irq(port->func);
 	port->ier = 0;
@@ -661,77 +755,70 @@ skip:
 	free_page((unsigned long)port->xmit.buf);
 }
 
-static int sdio_uart_open(struct tty_struct *tty, struct file *filp)
+/**
+ *	sdio_uart_install	-	install method
+ *	@driver: the driver in use (sdio_uart in our case)
+ *	@tty: the tty being bound
+ *
+ *	Look up and bind the tty and the driver together. Initialize
+ *	any needed private data (in our case the termios)
+ */
+
+static int sdio_uart_install(struct tty_driver *driver, struct tty_struct *tty)
 {
-	struct sdio_uart_port *port;
-	int ret;
+	int idx = tty->index;
+	struct sdio_uart_port *port = sdio_uart_port_get(idx);
+	int ret = tty_init_termios(tty);
+
+	if (ret == 0) {
+		tty_driver_kref_get(driver);
+		tty->count++;
+		/* This is the ref sdio_uart_port get provided */
+		tty->driver_data = port;
+		driver->ttys[idx] = tty;
+	} else
+		sdio_uart_port_put(port);
+	return ret;
+}
 
-	port = sdio_uart_port_get(tty->index);
-	if (!port)
-		return -ENODEV;
+/**
+ *	sdio_uart_cleanup	-	called on the last tty kref drop
+ *	@tty: the tty being destroyed
+ *
+ *	Called asynchronously when the last reference to the tty is dropped.
+ *	We cannot destroy the tty->driver_data port kref until this point
+ */
 
-	mutex_lock(&port->open_lock);
+static void sdio_uart_cleanup(struct tty_struct *tty)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+	tty->driver_data = NULL;	/* Bug trap */
+	sdio_uart_port_put(port);
+}
 
-	/*
-	 * Make sure not to mess up with a dead port
-	 * which has not been closed yet.
-	 */
-	if (tty->driver_data && tty->driver_data != port) {
-		mutex_unlock(&port->open_lock);
-		sdio_uart_port_put(port);
-		return -EBUSY;
-	}
+/*
+ *	Open/close/hangup is now entirely boilerplate
+ */
 
-	if (!port->opened) {
-		tty->driver_data = port;
-		port->tty = tty;
-		ret = sdio_uart_startup(port);
-		if (ret) {
-			tty->driver_data = NULL;
-			port->tty = NULL;
-			mutex_unlock(&port->open_lock);
-			sdio_uart_port_put(port);
-			return ret;
-		}
-	}
-	port->opened++;
-	mutex_unlock(&port->open_lock);
-	return 0;
+static int sdio_uart_open(struct tty_struct *tty, struct file *filp)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+	return tty_port_open(&port->port, tty, filp);
 }
 
 static void sdio_uart_close(struct tty_struct *tty, struct file * filp)
 {
 	struct sdio_uart_port *port = tty->driver_data;
+	tty_port_close(&port->port, tty, filp);
+}
 
-	if (!port)
-		return;
-
-	mutex_lock(&port->open_lock);
-	BUG_ON(!port->opened);
-
-	/*
-	 * This is messy.  The tty layer calls us even when open()
-	 * returned an error.  Ignore this close request if tty->count
-	 * is larger than port->count.
-	 */
-	if (tty->count > port->opened) {
-		mutex_unlock(&port->open_lock);
-		return;
-	}
-
-	if (--port->opened == 0) {
-		tty->closing = 1;
-		sdio_uart_shutdown(port);
-		tty_ldisc_flush(tty);
-		port->tty = NULL;
-		tty->driver_data = NULL;
-		tty->closing = 0;
-	}
-	mutex_unlock(&port->open_lock);
-	sdio_uart_port_put(port);
+static void sdio_uart_hangup(struct tty_struct *tty)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+	tty_port_hangup(&port->port);
 }
 
-static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf,
+static int sdio_uart_write(struct tty_struct *tty, const unsigned char *buf,
 			   int count)
 {
 	struct sdio_uart_port *port = tty->driver_data;
@@ -756,7 +843,7 @@ static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf,
 	}
 	spin_unlock(&port->write_lock);
 
-	if ( !(port->ier & UART_IER_THRI)) {
+	if (!(port->ier & UART_IER_THRI)) {
 		int err = sdio_uart_claim_func(port);
 		if (!err) {
 			sdio_uart_start_tx(port);
@@ -843,17 +930,12 @@ static void sdio_uart_unthrottle(struct tty_struct *tty)
 	sdio_uart_release_func(port);
 }
 
-static void sdio_uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+static void sdio_uart_set_termios(struct tty_struct *tty,
+						struct ktermios *old_termios)
 {
 	struct sdio_uart_port *port = tty->driver_data;
 	unsigned int cflag = tty->termios->c_cflag;
 
-#define RELEVANT_IFLAG(iflag)	((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
-	if ((cflag ^ old_termios->c_cflag) == 0 &&
-	    RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
-		return;
-
 	if (sdio_uart_claim_func(port) != 0)
 		return;
 
@@ -928,7 +1010,7 @@ static int sdio_uart_tiocmset(struct tty_struct *tty, struct file *file,
 	int result;
 
 	result = sdio_uart_claim_func(port);
-	if(!result) {
+	if (!result) {
 		sdio_uart_update_mctrl(port, set, clear);
 		sdio_uart_release_func(port);
 	}
@@ -946,7 +1028,7 @@ static int sdio_uart_proc_show(struct seq_file *m, void *v)
 		struct sdio_uart_port *port = sdio_uart_port_get(i);
 		if (port) {
 			seq_printf(m, "%d: uart:SDIO", i);
-			if(capable(CAP_SYS_ADMIN)) {
+			if (capable(CAP_SYS_ADMIN)) {
 				seq_printf(m, " tx:%d rx:%d",
 					      port->icount.tx, port->icount.rx);
 				if (port->icount.frame)
@@ -994,6 +1076,13 @@ static const struct file_operations sdio_uart_proc_fops = {
 	.release	= single_release,
 };
 
+static const struct tty_port_operations sdio_uart_port_ops = {
+	.dtr_rts = uart_dtr_rts,
+	.carrier_raised = uart_carrier_raised,
+	.shutdown = sdio_uart_shutdown,
+	.activate = sdio_uart_activate,
+};
+
 static const struct tty_operations sdio_uart_ops = {
 	.open			= sdio_uart_open,
 	.close			= sdio_uart_close,
@@ -1004,9 +1093,12 @@ static const struct tty_operations sdio_uart_ops = {
 	.throttle		= sdio_uart_throttle,
 	.unthrottle		= sdio_uart_unthrottle,
 	.set_termios		= sdio_uart_set_termios,
+	.hangup			= sdio_uart_hangup,
 	.break_ctl		= sdio_uart_break_ctl,
 	.tiocmget		= sdio_uart_tiocmget,
 	.tiocmset		= sdio_uart_tiocmset,
+	.install		= sdio_uart_install,
+	.cleanup		= sdio_uart_cleanup,
 	.proc_fops		= &sdio_uart_proc_fops,
 };
 
@@ -1043,7 +1135,7 @@ static int sdio_uart_probe(struct sdio_func *func,
 		}
 		if (!tpl) {
 			printk(KERN_WARNING
-			       "%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n",
+       "%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n",
 			       sdio_func_id(func));
 			kfree(port);
 			return -EINVAL;
@@ -1068,13 +1160,16 @@ static int sdio_uart_probe(struct sdio_func *func,
 
 	port->func = func;
 	sdio_set_drvdata(func, port);
+	tty_port_init(&port->port);
+	port->port.ops = &sdio_uart_port_ops;
 
 	ret = sdio_uart_add_port(port);
 	if (ret) {
 		kfree(port);
 	} else {
 		struct device *dev;
-		dev = tty_register_device(sdio_uart_tty_driver, port->index, &func->dev);
+		dev = tty_register_device(sdio_uart_tty_driver,
+						port->index, &func->dev);
 		if (IS_ERR(dev)) {
 			sdio_uart_port_remove(port);
 			ret = PTR_ERR(dev);
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 737b4c960971..c3e37c8e7e26 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -1339,14 +1339,12 @@ static void serial8250_start_tx(struct uart_port *port)
 		serial_out(up, UART_IER, up->ier);
 
 		if (up->bugs & UART_BUG_TXEN) {
-			unsigned char lsr, iir;
+			unsigned char lsr;
 			lsr = serial_in(up, UART_LSR);
 			up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
-			iir = serial_in(up, UART_IIR) & 0x0f;
 			if ((up->port.type == PORT_RM9000) ?
-				(lsr & UART_LSR_THRE &&
-				(iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) :
-				(lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT))
+				(lsr & UART_LSR_THRE) :
+				(lsr & UART_LSR_TEMT))
 				transmit_chars(up);
 		}
 	}
@@ -2646,7 +2644,7 @@ static void __init serial8250_isa_init_ports(void)
 {
 	struct uart_8250_port *up;
 	static int first = 1;
-	int i;
+	int i, irqflag = 0;
 
 	if (!first)
 		return;
@@ -2670,6 +2668,9 @@ static void __init serial8250_isa_init_ports(void)
 		up->port.ops = &serial8250_pops;
 	}
 
+	if (share_irqs)
+		irqflag = IRQF_SHARED;
+
 	for (i = 0, up = serial8250_ports;
 	     i < ARRAY_SIZE(old_serial_port) && i < nr_uarts;
 	     i++, up++) {
@@ -2683,8 +2684,7 @@ static void __init serial8250_isa_init_ports(void)
 		up->port.iotype   = old_serial_port[i].io_type;
 		up->port.regshift = old_serial_port[i].iomem_reg_shift;
 		set_io_from_upio(&up->port);
-		if (share_irqs)
-			up->port.irqflags |= IRQF_SHARED;
+		up->port.irqflags |= irqflag;
 	}
 }
 
@@ -2940,10 +2940,13 @@ static int __devinit serial8250_probe(struct platform_device *dev)
 {
 	struct plat_serial8250_port *p = dev->dev.platform_data;
 	struct uart_port port;
-	int ret, i;
+	int ret, i, irqflag = 0;
 
 	memset(&port, 0, sizeof(struct uart_port));
 
+	if (share_irqs)
+		irqflag = IRQF_SHARED;
+
 	for (i = 0; p && p->flags != 0; p++, i++) {
 		port.iobase		= p->iobase;
 		port.membase		= p->membase;
@@ -2960,8 +2963,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
 		port.serial_in		= p->serial_in;
 		port.serial_out		= p->serial_out;
 		port.dev		= &dev->dev;
-		if (share_irqs)
-			port.irqflags |= IRQF_SHARED;
+		port.irqflags		|= irqflag;
 		ret = serial8250_register_port(&port);
 		if (ret < 0) {
 			dev_err(&dev->dev, "unable to register port at index %d "
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h
index 4e5f3bde0461..38a509c684cd 100644
--- a/drivers/serial/jsm/jsm.h
+++ b/drivers/serial/jsm/jsm.h
@@ -138,7 +138,6 @@ struct jsm_board
 	u32		nasync;		/* Number of ports on card */
 
 	u32		irq;		/* Interrupt request number */
-	u64		intr_count;	/* Count of interrupts */
 
 	u64		membase;	/* Start of base memory of the card */
 	u64		membase_end;	/* End of base memory of the card */
@@ -206,8 +205,6 @@ struct jsm_channel {
 
 	u64		ch_close_delay;	/* How long we should drop RTS/DTR for */
 
-	u64		ch_cpstime;	/* Time for CPS calculations	*/
-
 	tcflag_t	ch_c_iflag;	/* channel iflags		*/
 	tcflag_t	ch_c_cflag;	/* channel cflags		*/
 	tcflag_t	ch_c_oflag;	/* channel oflags		*/
@@ -215,11 +212,6 @@ struct jsm_channel {
 	u8		ch_stopc;	/* Stop character		*/
 	u8		ch_startc;	/* Start character		*/
 
-	u32		ch_old_baud;	/* Cache of the current baud */
-	u32		ch_custom_speed;/* Custom baud, if set */
-
-	u32		ch_wopen;	/* Waiting for open process cnt */
-
 	u8		ch_mostat;	/* FEP output modem status	*/
 	u8		ch_mistat;	/* FEP input modem status	*/
 
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index b3604aa322a4..108c3e0471fd 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -48,6 +48,17 @@ struct uart_driver jsm_uart_driver = {
 	.nr		= NR_PORTS,
 };
 
+static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev,
+                                       pci_channel_state_t state);
+static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev);
+static void jsm_io_resume(struct pci_dev *pdev);
+
+static struct pci_error_handlers jsm_err_handler = {
+	.error_detected = jsm_io_error_detected,
+	.slot_reset = jsm_io_slot_reset,
+	.resume = jsm_io_resume,
+};
+
 int jsm_debug;
 module_param(jsm_debug, int, 0);
 MODULE_PARM_DESC(jsm_debug, "Driver debugging level");
@@ -123,7 +134,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device
 	}
 
 	rc = request_irq(brd->irq, brd->bd_ops->intr,
-			IRQF_DISABLED|IRQF_SHARED, "JSM", brd);
+			IRQF_SHARED, "JSM", brd);
 	if (rc) {
 		printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq);
 		goto out_iounmap;
@@ -164,6 +175,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device
 	}
 
 	pci_set_drvdata(pdev, brd);
+	pci_save_state(pdev);
 
 	return 0;
  out_free_irq:
@@ -222,8 +234,42 @@ static struct pci_driver jsm_driver = {
 	.id_table	= jsm_pci_tbl,
 	.probe		= jsm_probe_one,
 	.remove		= __devexit_p(jsm_remove_one),
+	.err_handler    = &jsm_err_handler,
 };
 
+static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev,
+					pci_channel_state_t state)
+{
+	struct jsm_board *brd = pci_get_drvdata(pdev);
+
+	jsm_remove_uart_port(brd);
+
+	return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev)
+{
+	int rc;
+
+	rc = pci_enable_device(pdev);
+
+	if (rc)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	pci_set_master(pdev);
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+static void jsm_io_resume(struct pci_dev *pdev)
+{
+	struct jsm_board *brd = pci_get_drvdata(pdev);
+
+	pci_restore_state(pdev);
+
+	jsm_uart_port_init(brd);
+}
+
 static int __init jsm_init_module(void)
 {
 	int rc;
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c
index b4b124e4828f..7960d9633c15 100644
--- a/drivers/serial/jsm/jsm_neo.c
+++ b/drivers/serial/jsm/jsm_neo.c
@@ -954,13 +954,8 @@ static void neo_param(struct jsm_channel *ch)
 		ch->ch_flags |= (CH_BAUD0);
 		ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR);
 		neo_assert_modem_signals(ch);
-		ch->ch_old_baud = 0;
 		return;
 
-	} else if (ch->ch_custom_speed) {
-			baud = ch->ch_custom_speed;
-			if (ch->ch_flags & CH_BAUD0)
-				ch->ch_flags &= ~(CH_BAUD0);
 	} else {
 		int i;
 		unsigned int cflag;
@@ -1045,7 +1040,6 @@ static void neo_param(struct jsm_channel *ch)
 	quot = ch->ch_bd->bd_dividend / baud;
 
 	if (quot != 0) {
-		ch->ch_old_baud = baud;
 		writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr);
 		writeb((quot & 0xff), &ch->ch_neo_uart->txrx);
 		writeb((quot >> 8), &ch->ch_neo_uart->ier);
@@ -1123,8 +1117,6 @@ static irqreturn_t neo_intr(int irq, void *voidbrd)
 	unsigned long lock_flags2;
 	int outofloop_count = 0;
 
-	brd->intr_count++;
-
 	/* Lock out the slow poller from running on this board. */
 	spin_lock_irqsave(&brd->bd_intr_lock, lock_flags);
 
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
index 7439c0373620..cd95e215550d 100644
--- a/drivers/serial/jsm/jsm_tty.c
+++ b/drivers/serial/jsm/jsm_tty.c
@@ -296,8 +296,6 @@ static void jsm_tty_close(struct uart_port *port)
 		bd->bd_ops->assert_modem_signals(channel);
 	}
 
-	channel->ch_old_baud = 0;
-
 	/* Turn off UART interrupts for this port */
 	channel->ch_bd->bd_ops->uart_off(channel);
 
@@ -432,7 +430,7 @@ int __devinit jsm_tty_init(struct jsm_board *brd)
 	return 0;
 }
 
-int __devinit jsm_uart_port_init(struct jsm_board *brd)
+int jsm_uart_port_init(struct jsm_board *brd)
 {
 	int i;
 	unsigned int line;
@@ -472,7 +470,7 @@ int __devinit jsm_uart_port_init(struct jsm_board *brd)
 		if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port))
 			printk(KERN_INFO "jsm: add device failed\n");
 		else
-			printk(KERN_INFO "Added device \n");
+			printk(KERN_INFO "jsm: Port %d added\n", i);
 	}
 
 	jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index b8629d74f6a2..4a821046baae 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -438,6 +438,7 @@ serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
 	unsigned char cval, fcr = 0;
 	unsigned long flags;
 	unsigned int baud, quot;
+	unsigned int dll;
 
 	switch (termios->c_cflag & CSIZE) {
 	case CS5:
@@ -534,10 +535,18 @@ serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
 	else
 		up->mcr &= ~UART_MCR_AFE;
 
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
+	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
 	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
+
+	/*
+	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
+	 * Specification Update (Nov 2005)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (quot & 0xff));
+
 	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);		/* reset DLAB */
+	serial_out(up, UART_LCR, cval);			/* reset DLAB */
 	up->lcr = cval;					/* Save LCR */
 	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
 	serial_out(up, UART_FCR, fcr);
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index dcc72444e8e7..047530b285bb 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -342,11 +342,11 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
 
 	if (flags == UPF_SPD_HI)
 		altbaud = 57600;
-	if (flags == UPF_SPD_VHI)
+	else if (flags == UPF_SPD_VHI)
 		altbaud = 115200;
-	if (flags == UPF_SPD_SHI)
+	else if (flags == UPF_SPD_SHI)
 		altbaud = 230400;
-	if (flags == UPF_SPD_WARP)
+	else if (flags == UPF_SPD_WARP)
 		altbaud = 460800;
 
 	for (try = 0; try < 2; try++) {
@@ -1217,9 +1217,8 @@ static void uart_set_termios(struct tty_struct *tty,
 	/* Handle transition to B0 status */
 	if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
 		uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR);
-
 	/* Handle transition away from B0 status */
-	if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
+	else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
 		unsigned int mask = TIOCM_DTR;
 		if (!(cflag & CRTSCTS) ||
 		    !test_bit(TTY_THROTTLED, &tty->flags))
@@ -1234,9 +1233,8 @@ static void uart_set_termios(struct tty_struct *tty,
 		__uart_start(tty);
 		spin_unlock_irqrestore(&state->uart_port->lock, flags);
 	}
-
 	/* Handle turning on CRTSCTS */
-	if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
+	else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
 		spin_lock_irqsave(&state->uart_port->lock, flags);
 		if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) {
 			tty->hw_stopped = 1;
@@ -2344,7 +2342,7 @@ static const struct tty_operations uart_ops = {
  */
 int uart_register_driver(struct uart_driver *drv)
 {
-	struct tty_driver *normal = NULL;
+	struct tty_driver *normal;
 	int i, retval;
 
 	BUG_ON(drv->state);
@@ -2354,13 +2352,12 @@ int uart_register_driver(struct uart_driver *drv)
 	 * we have a large number of ports to handle.
 	 */
 	drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
-	retval = -ENOMEM;
 	if (!drv->state)
 		goto out;
 
-	normal  = alloc_tty_driver(drv->nr);
+	normal = alloc_tty_driver(drv->nr);
 	if (!normal)
-		goto out;
+		goto out_kfree;
 
 	drv->tty_driver = normal;
 
@@ -2393,12 +2390,14 @@ int uart_register_driver(struct uart_driver *drv)
 	}
 
 	retval = tty_register_driver(normal);
- out:
-	if (retval < 0) {
-		put_tty_driver(normal);
-		kfree(drv->state);
-	}
-	return retval;
+	if (retval >= 0)
+		return retval;
+
+	put_tty_driver(normal);
+out_kfree:
+	kfree(drv->state);
+out:
+	return -ENOMEM;
 }
 
 /**
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index 80f59b6350cb..4cdb975caa89 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -501,12 +501,13 @@ static int opticon_resume(struct usb_interface *intf)
 	struct usb_serial_port *port = serial->port[0];
 	int result;
 
-	mutex_lock(&port->mutex);
-	if (port->port.count)
+	mutex_lock(&port->port.mutex);
+	/* This is protected by the port mutex against close/open */
+	if (test_bit(ASYNCB_INITIALIZED, &port->port.flags))
 		result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO);
 	else
 		result = 0;
-	mutex_unlock(&port->mutex);
+	mutex_unlock(&port->port.mutex);
 	return result;
 }
 
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index bd3fa7ff15b1..4543f359be75 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -247,96 +247,66 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
 	return retval;
 }
 
-static int serial_open(struct tty_struct *tty, struct file *filp)
+static int serial_activate(struct tty_port *tport, struct tty_struct *tty)
 {
-	struct usb_serial_port *port = tty->driver_data;
+	struct usb_serial_port *port =
+		container_of(tport, struct usb_serial_port, port);
 	struct usb_serial *serial = port->serial;
 	int retval;
 
-	dbg("%s - port %d", __func__, port->number);
-
-	spin_lock_irq(&port->port.lock);
-	if (!tty_hung_up_p(filp))
-		++port->port.count;
-	spin_unlock_irq(&port->port.lock);
-	tty_port_tty_set(&port->port, tty);
+	mutex_lock(&serial->disc_mutex);
+	if (serial->disconnected)
+		retval = -ENODEV;
+	else
+		retval = port->serial->type->open(tty, port);
+	mutex_unlock(&serial->disc_mutex);
+	return retval;
+}
 
-	/* Do the device-specific open only if the hardware isn't
-	 * already initialized.
-	 */
-	if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) {
-		if (mutex_lock_interruptible(&port->mutex))
-			return -ERESTARTSYS;
-		mutex_lock(&serial->disc_mutex);
-		if (serial->disconnected)
-			retval = -ENODEV;
-		else
-			retval = port->serial->type->open(tty, port);
-		mutex_unlock(&serial->disc_mutex);
-		mutex_unlock(&port->mutex);
-		if (retval)
-			return retval;
-		set_bit(ASYNCB_INITIALIZED, &port->port.flags);
-	}
+static int serial_open(struct tty_struct *tty, struct file *filp)
+{
+	struct usb_serial_port *port = tty->driver_data;
 
-	/* Now do the correct tty layer semantics */
-	retval = tty_port_block_til_ready(&port->port, tty, filp);
-	return retval;
+	dbg("%s - port %d", __func__, port->number);
+	return tty_port_open(&port->port, tty, filp);
 }
 
 /**
  * serial_down - shut down hardware
- * @port: port to shut down
+ * @tport: tty port to shut down
  *
  * Shut down a USB serial port unless it is the console.  We never
- * shut down the console hardware as it will always be in use.
+ * shut down the console hardware as it will always be in use. Serialized
+ * against activate by the tport mutex and kept to matching open/close pairs
+ * of calls by the ASYNCB_INITIALIZED flag.
  */
-static void serial_down(struct usb_serial_port *port)
+static void serial_down(struct tty_port *tport)
 {
+	struct usb_serial_port *port =
+		container_of(tport, struct usb_serial_port, port);
 	struct usb_serial_driver *drv = port->serial->type;
-
 	/*
 	 * The console is magical.  Do not hang up the console hardware
 	 * or there will be tears.
 	 */
 	if (port->console)
 		return;
-
-	/* Don't call the close method if the hardware hasn't been
-	 * initialized.
-	 */
-	if (!test_and_clear_bit(ASYNCB_INITIALIZED, &port->port.flags))
-		return;
-
-	mutex_lock(&port->mutex);
 	if (drv->close)
 		drv->close(port);
-	mutex_unlock(&port->mutex);
 }
 
 static void serial_hangup(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
-
 	dbg("%s - port %d", __func__, port->number);
-
-	serial_down(port);
 	tty_port_hangup(&port->port);
 }
 
 static void serial_close(struct tty_struct *tty, struct file *filp)
 {
 	struct usb_serial_port *port = tty->driver_data;
-
 	dbg("%s - port %d", __func__, port->number);
-
-	if (tty_hung_up_p(filp))
-		return;
-	if (tty_port_close_start(&port->port, tty, filp) == 0)
-		return;
-	serial_down(port);
-	tty_port_close_end(&port->port, tty);
-	tty_port_tty_set(&port->port, NULL);
+	tty_port_close(&port->port, tty, filp);
 }
 
 /**
@@ -725,6 +695,8 @@ static void serial_dtr_rts(struct tty_port *port, int on)
 static const struct tty_port_operations serial_port_ops = {
 	.carrier_raised = serial_carrier_raised,
 	.dtr_rts = serial_dtr_rts,
+	.activate = serial_activate,
+	.shutdown = serial_down,
 };
 
 int usb_serial_probe(struct usb_interface *interface,
@@ -923,7 +895,8 @@ int usb_serial_probe(struct usb_interface *interface,
 		port->port.ops = &serial_port_ops;
 		port->serial = serial;
 		spin_lock_init(&port->lock);
-		mutex_init(&port->mutex);
+		/* Keep this for private driver use for the moment but
+		   should probably go away */
 		INIT_WORK(&port->work, usb_serial_port_work);
 		serial->port[i] = port;
 		port->dev.parent = &interface->dev;
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index d5f8c96964be..8882ecc0f1bf 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -517,11 +517,23 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)
 
 struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number)
 {
+	struct dentry *dentry;
+	struct tty_struct *tty;
+
 	BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
 
+	/* Ensure dentry has not been deleted by devpts_pty_kill() */
+	dentry = d_find_alias(pts_inode);
+	if (!dentry)
+		return NULL;
+
+	tty = NULL;
 	if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
-		return (struct tty_struct *)pts_inode->i_private;
-	return NULL;
+		tty = (struct tty_struct *)pts_inode->i_private;
+
+	dput(dentry);
+
+	return tty;
 }
 
 void devpts_pty_kill(struct tty_struct *tty)
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 5a5385749e16..f72914db2a11 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -214,7 +214,6 @@ unifdef-y += futex.h
 unifdef-y += fs.h
 unifdef-y += gameport.h
 unifdef-y += generic_serial.h
-unifdef-y += hayesesp.h
 unifdef-y += hdlcdrv.h
 unifdef-y += hdlc.h
 unifdef-y += hdreg.h
diff --git a/include/linux/hayesesp.h b/include/linux/hayesesp.h
deleted file mode 100644
index 92b08cfe4a75..000000000000
--- a/include/linux/hayesesp.h
+++ /dev/null
@@ -1,114 +0,0 @@
-#ifndef HAYESESP_H
-#define HAYESESP_H
-
-struct hayes_esp_config {
-	short flow_on;
-	short flow_off;
-	short rx_trigger;
-	short tx_trigger;
-	short pio_threshold;
-	unsigned char rx_timeout;
-	char dma_channel;
-};
-
-#ifdef __KERNEL__
-
-#define ESP_DMA_CHANNEL   0
-#define ESP_RX_TRIGGER    768
-#define ESP_TX_TRIGGER    768
-#define ESP_FLOW_OFF      1016
-#define ESP_FLOW_ON       944
-#define ESP_RX_TMOUT      128
-#define ESP_PIO_THRESHOLD 32
-
-#define ESP_IN_MAJOR	57	/* major dev # for dial in */
-#define ESP_OUT_MAJOR	58	/* major dev # for dial out */
-#define ESPC_SCALE 	3
-#define UART_ESI_BASE	0x00
-#define UART_ESI_SID	0x01
-#define UART_ESI_RX	0x02
-#define UART_ESI_TX	0x02
-#define UART_ESI_CMD1	0x04
-#define UART_ESI_CMD2	0x05
-#define UART_ESI_STAT1	0x04
-#define UART_ESI_STAT2	0x05
-#define UART_ESI_RWS	0x07
-
-#define UART_IER_DMA_TMOUT	0x80
-#define UART_IER_DMA_TC		0x08
-
-#define ESI_SET_IRQ		0x04
-#define ESI_SET_DMA_TMOUT	0x05
-#define ESI_SET_SRV_MASK	0x06
-#define ESI_SET_ERR_MASK	0x07
-#define ESI_SET_FLOW_CNTL	0x08
-#define ESI_SET_FLOW_CHARS	0x09
-#define ESI_SET_FLOW_LVL	0x0a
-#define ESI_SET_TRIGGER		0x0b
-#define ESI_SET_RX_TIMEOUT	0x0c
-#define ESI_SET_FLOW_TMOUT	0x0d
-#define ESI_WRITE_UART		0x0e
-#define ESI_READ_UART		0x0f
-#define ESI_SET_MODE		0x10
-#define ESI_GET_ERR_STAT	0x12
-#define ESI_GET_UART_STAT	0x13
-#define ESI_GET_RX_AVAIL	0x14
-#define ESI_GET_TX_AVAIL	0x15
-#define ESI_START_DMA_RX	0x16
-#define ESI_START_DMA_TX	0x17
-#define ESI_ISSUE_BREAK		0x1a
-#define ESI_FLUSH_RX		0x1b
-#define ESI_FLUSH_TX		0x1c
-#define ESI_SET_BAUD		0x1d
-#define ESI_SET_ENH_IRQ		0x1f
-#define ESI_SET_REINTR		0x20
-#define ESI_SET_PRESCALAR	0x23
-#define ESI_NO_COMMAND		0xff
-
-#define ESP_STAT_RX_TIMEOUT	0x01
-#define ESP_STAT_DMA_RX		0x02
-#define ESP_STAT_DMA_TX		0x04
-#define ESP_STAT_NEVER_DMA      0x08
-#define ESP_STAT_USE_PIO        0x10
-
-#define ESP_MAGIC		0x53ee
-#define ESP_XMIT_SIZE		4096
-
-struct esp_struct {
-	int			magic;
-	struct tty_port		port;
-	spinlock_t		lock;
-	int			io_port;
-	int			irq;
-	int			read_status_mask;
-	int			ignore_status_mask;
-	int			timeout;
-	int			stat_flags;
-	int			custom_divisor;
-	int			close_delay;
-	unsigned short		closing_wait;
-	unsigned short		closing_wait2;
-	int			IER; 	/* Interrupt Enable Register */
-	int			MCR; 	/* Modem control register */
-	unsigned long		last_active;
-	int			line;
-	unsigned char 		*xmit_buf;
-	int			xmit_head;
-	int			xmit_tail;
-	int			xmit_cnt;
-	wait_queue_head_t	break_wait;
-	struct async_icount	icount;	/* kernel counters for the 4 input interrupts */
-	struct hayes_esp_config config; /* port configuration */
-	struct esp_struct	*next_port; /* For the linked list */
-};
-
-struct esp_pio_buffer {
-	unsigned char data[1024];
-	struct esp_pio_buffer *next;
-};
-
-#endif /* __KERNEL__ */
-
-
-#endif /* ESP_H */
-
diff --git a/include/linux/isicom.h b/include/linux/isicom.h
index bbd42197298f..b92e05650639 100644
--- a/include/linux/isicom.h
+++ b/include/linux/isicom.h
@@ -67,6 +67,7 @@
 
 #define		FIRMWARE_LOADED		0x0001
 #define		BOARD_ACTIVE		0x0002
+#define		BOARD_INIT		0x0004
 
  	/* isi_port status bitmap  */
 
diff --git a/include/linux/tty.h b/include/linux/tty.h
index f0f43d08d8b8..405a9035fe40 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -190,9 +190,17 @@ struct tty_port_operations {
 	/* Control the DTR line */
 	void (*dtr_rts)(struct tty_port *port, int raise);
 	/* Called when the last close completes or a hangup finishes
-	   IFF the port was initialized. Do not use to free resources */
+	   IFF the port was initialized. Do not use to free resources. Called
+	   under the port mutex to serialize against activate/shutdowns */
 	void (*shutdown)(struct tty_port *port);
 	void (*drop)(struct tty_port *port);
+	/* Called under the port mutex from tty_port_open, serialized using
+	   the port mutex */
+        /* FIXME: long term getting the tty argument *out* of this would be
+           good for consoles */
+	int (*activate)(struct tty_port *port, struct tty_struct *tty);
+	/* Called on the final put of a port */
+	void (*destruct)(struct tty_port *port);
 };
 	
 struct tty_port {
@@ -206,12 +214,14 @@ struct tty_port {
 	wait_queue_head_t	delta_msr_wait;	/* Modem status change */
 	unsigned long		flags;		/* TTY flags ASY_*/
 	struct mutex		mutex;		/* Locking */
+	struct mutex		buf_mutex;	/* Buffer alloc lock */
 	unsigned char		*xmit_buf;	/* Optional buffer */
 	unsigned int		close_delay;	/* Close port delay */
 	unsigned int		closing_wait;	/* Delay for output */
 	int			drain_delay;	/* Set to zero if no pure time
 						   based drain is needed else
 						   set to size of fifo */
+	struct kref		kref;		/* Ref counter */
 };
 
 /*
@@ -439,7 +449,7 @@ extern void initialize_tty_struct(struct tty_struct *tty,
 		struct tty_driver *driver, int idx);
 extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
 								int first_ok);
-extern void tty_release_dev(struct file *filp);
+extern int tty_release(struct inode *inode, struct file *filp);
 extern int tty_init_termios(struct tty_struct *tty);
 
 extern struct tty_struct *tty_pair_get_tty(struct tty_struct *tty);
@@ -454,6 +464,15 @@ extern int tty_write_lock(struct tty_struct *tty, int ndelay);
 extern void tty_port_init(struct tty_port *port);
 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);
+
+extern inline struct tty_port *tty_port_get(struct tty_port *port)
+{
+	if (port)
+		kref_get(&port->kref);
+	return port;
+}
+
 extern struct tty_struct *tty_port_tty_get(struct tty_port *port);
 extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty);
 extern int tty_port_carrier_raised(struct tty_port *port);
@@ -467,6 +486,8 @@ extern int tty_port_close_start(struct tty_port *port,
 extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
 extern void tty_port_close(struct tty_port *port,
 				struct tty_struct *tty, struct file *filp);
+extern int tty_port_open(struct tty_port *port,
+				struct tty_struct *tty, struct file *filp);
 extern inline int tty_port_users(struct tty_port *port)
 {
 	return port->count + port->blocked_open;
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index ce911ebf91e8..acf6e457c04b 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -39,8 +39,6 @@ enum port_dev_state {
  * @serial: pointer back to the struct usb_serial owner of this port.
  * @port: pointer to the corresponding tty_port for this port.
  * @lock: spinlock to grab when updating portions of this structure.
- * @mutex: mutex used to synchronize serial_open() and serial_close()
- *	access for this port.
  * @number: the number of the port (the minor number).
  * @interrupt_in_buffer: pointer to the interrupt in buffer for this port.
  * @interrupt_in_urb: pointer to the interrupt in struct urb for this port.
@@ -77,7 +75,6 @@ struct usb_serial_port {
 	struct usb_serial	*serial;
 	struct tty_port		port;
 	spinlock_t		lock;
-	struct mutex            mutex;
 	unsigned char		number;
 
 	unsigned char		*interrupt_in_buffer;
diff --git a/kernel/exit.c b/kernel/exit.c
index 1143012951e9..6f50ef55a6f3 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -971,7 +971,7 @@ NORET_TYPE void do_exit(long code)
 	exit_thread();
 	cgroup_exit(tsk, 1);
 
-	if (group_dead && tsk->signal->leader)
+	if (group_dead)
 		disassociate_ctty(1);
 
 	module_put(task_thread_info(tsk)->exec_domain->module);