diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index ea3f6bedf239bc40421df0d924d07e156e374954..ba16a21a7a051c52510f1fb48063b43a0b9569d3 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -122,13 +122,13 @@ struct uart_8250_port {
 	struct uart_port	port;
 	struct timer_list	timer;		/* "no irq" timer */
 	struct list_head	list;		/* ports on this IRQ */
+	unsigned short		rev;
 	unsigned char		acr;
 	unsigned char		ier;
-	unsigned char		rev;
 	unsigned char		lcr;
 	unsigned char		mcr_mask;	/* mask of user bits */
 	unsigned char		mcr_force;	/* mask of forced bits */
-	unsigned int		lsr_break_flag;
+	unsigned char		lsr_break_flag;
 
 	/*
 	 * We provide a per-port pm hook.
diff --git a/drivers/serial/8250_cs.c b/drivers/serial/8250_cs.c
index 135699e8fad275f65cfb2a4e574ab00132150e6a..c10b031bc0aea4b923758a3f1ef7e695439993a5 100644
--- a/drivers/serial/8250_cs.c
+++ b/drivers/serial/8250_cs.c
@@ -2,7 +2,7 @@
 
     A driver for PCMCIA serial devices
 
-    serial_cs.c 1.123 2000/08/24 18:46:38
+    serial_cs.c 1.134 2002/05/04 05:48:53
 
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -43,7 +43,6 @@
 #include <linux/serial.h>
 #include <linux/serial_core.h>
 #include <linux/major.h>
-#include <linux/workqueue.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -59,7 +58,7 @@
 static int pc_debug = PCMCIA_DEBUG;
 MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-static char *version = "serial_cs.c 1.123 2000/08/24 18:46:38 (David Hinds)";
+static char *version = "serial_cs.c 1.134 2002/05/04 05:48:53 (David Hinds)";
 #else
 #define DEBUG(n, args...)
 #endif
@@ -74,10 +73,13 @@ static int irq_list[4] = { -1 };
 
 /* Enable the speaker? */
 static int do_sound = 1;
+/* Skip strict UART tests? */
+static int buggy_uart;
 
 MODULE_PARM(irq_mask, "i");
 MODULE_PARM(irq_list, "1-4i");
 MODULE_PARM(do_sound, "i");
+MODULE_PARM(buggy_uart, "i");
 
 /*====================================================================*/
 
@@ -100,7 +102,7 @@ static struct multi_id multi_id[] = {
 };
 #define MULTI_COUNT (sizeof(multi_id)/sizeof(struct multi_id))
 
-typedef struct serial_info {
+struct serial_info {
 	dev_link_t		link;
 	int			ndev;
 	int			multi;
@@ -108,8 +110,7 @@ typedef struct serial_info {
 	int			manfid;
 	dev_node_t		node[4];
 	int			line[4];
-	struct work_struct	remove;
-} serial_info_t;
+};
 
 static void serial_config(dev_link_t * link);
 static int serial_event(event_t event, int priority,
@@ -124,20 +125,19 @@ static dev_link_t *dev_list = NULL;
 
 /*======================================================================
 
-    After a card is removed, do_serial_release() will unregister
+    After a card is removed, serial_remove() will unregister
     the serial device(s), and release the PCMCIA configuration.
     
 ======================================================================*/
 
-/*
- * This always runs in process context.
- */
-static void do_serial_release(void *arg)
+static void serial_remove(dev_link_t *link)
 {
-	struct serial_info *info = arg;
-	int i;
+	struct serial_info *info = link->priv;
+	int i, ret;
 
-	DEBUG(0, "serial_release(0x%p)\n", &info->link);
+	link->state &= ~DEV_PRESENT;
+
+	DEBUG(0, "serial_release(0x%p)\n", link);
 
 	/*
 	 * Recheck to see if the device is still configured.
@@ -158,25 +158,6 @@ static void do_serial_release(void *arg)
 	}
 }
 
-/*
- * This may be called from IRQ context.
- */
-static void serial_remove(dev_link_t *link)
-{
-	struct serial_info *info = link->priv;
-
-	link->state &= ~DEV_PRESENT;
-
-	/*
-	 * FIXME: Since the card has probably been removed,
-	 * we should call into the serial layer and hang up
-	 * the ports on the card immediately.
-	 */
-
-	if (link->state & DEV_CONFIG)
-		schedule_work(&info->remove);
-}
-
 /*======================================================================
 
     serial_attach() creates an "instance" of the driver, allocating
@@ -187,7 +168,7 @@ static void serial_remove(dev_link_t *link)
 
 static dev_link_t *serial_attach(void)
 {
-	serial_info_t *info;
+	struct serial_info *info;
 	client_reg_t client_reg;
 	dev_link_t *link;
 	int i, ret;
@@ -202,8 +183,6 @@ static dev_link_t *serial_attach(void)
 	link = &info->link;
 	link->priv = info;
 
-	INIT_WORK(&info->remove, do_serial_release, info);
-
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
 	link->io.NumPorts1 = 8;
 	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
@@ -214,7 +193,6 @@ static dev_link_t *serial_attach(void)
 		for (i = 0; i < 4; i++)
 			link->irq.IRQInfo2 |= 1 << irq_list[i];
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.Vcc = 50;
 	if (do_sound) {
 		link->conf.Attributes |= CONF_ENABLE_SPKR;
 		link->conf.Status = CCSR_AUDIO_ENA;
@@ -254,7 +232,7 @@ static dev_link_t *serial_attach(void)
 
 static void serial_detach(dev_link_t * link)
 {
-	serial_info_t *info = link->priv;
+	struct serial_info *info = link->priv;
 	dev_link_t **linkp;
 	int ret;
 
@@ -275,7 +253,7 @@ static void serial_detach(dev_link_t * link)
 	/*
 	 * Ensure that the ports have been released.
 	 */
-	do_serial_release(info);
+	serial_remove(link);
 
 	if (link->handle) {
 		ret = CardServices(DeregisterClient, link->handle);
@@ -290,7 +268,7 @@ static void serial_detach(dev_link_t * link)
 
 /*====================================================================*/
 
-static int setup_serial(serial_info_t * info, ioaddr_t port, int irq)
+static int setup_serial(struct serial_info * info, ioaddr_t port, int irq)
 {
 	struct serial_struct serial;
 	int line;
@@ -299,11 +277,13 @@ static int setup_serial(serial_info_t * info, ioaddr_t port, int irq)
 	serial.port = port;
 	serial.irq = irq;
 	serial.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ;
+	if (buggy_uart)
+		serial.flags |= UPF_BUGGY_UART;
 	line = register_serial(&serial);
 	if (line < 0) {
 		printk(KERN_NOTICE "serial_cs: register_serial() at 0x%04lx,"
 		       " irq %d failed\n", (u_long) serial.port, serial.irq);
-		return -1;
+		return -EINVAL;
 	}
 
 	info->line[info->ndev] = line;
@@ -341,7 +321,7 @@ static int simple_config(dev_link_t * link)
 {
 	static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
 	client_handle_t handle = link->handle;
-	serial_info_t *info = link->priv;
+	struct serial_info *info = link->priv;
 	tuple_t tuple;
 	u_char buf[256];
 	cisparse_t parse;
@@ -445,13 +425,21 @@ static int simple_config(dev_link_t * link)
 static int multi_config(dev_link_t * link)
 {
 	client_handle_t handle = link->handle;
-	serial_info_t *info = link->priv;
+	struct serial_info *info = link->priv;
 	tuple_t tuple;
 	u_char buf[256];
 	cisparse_t parse;
 	cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+	config_info_t config;
 	int i, base2 = 0;
 
+	i = CardServices(GetConfigurationInfo, handle, &config);
+	if (i != CS_SUCCESS) {
+		cs_error(handle, GetConfiguration, i);
+		return -1;
+	}
+	link->conf.Vcc = config.Vcc;
+
 	tuple.TupleData = (cisdata_t *) buf;
 	tuple.TupleOffset = 0;
 	tuple.TupleDataMax = 255;
@@ -524,6 +512,19 @@ static int multi_config(dev_link_t * link)
 		return -1;
 	}
 
+	/* The Oxford Semiconductor OXCF950 cards are in fact single-port:
+	   8 registers are for the UART, the others are extra registers */
+	if (info->manfid == MANFID_OXSEMI) {
+		if (cf->index == 1 || cf->index == 3) {
+			setup_serial(info, base2, link->irq.AssignedIRQ);
+			outb(12, link->io.BasePort1 + 1);
+		} else {
+			setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ);
+			outb(12, base2 + 1);
+		}
+		return 0;
+	}
+
 	setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ);
 	/* The Nokia cards are not really multiport cards */
 	if (info->manfid == MANFID_NOKIA)
@@ -548,7 +549,7 @@ while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
 void serial_config(dev_link_t * link)
 {
 	client_handle_t handle = link->handle;
-	serial_info_t *info = link->priv;
+	struct serial_info *info = link->priv;
 	tuple_t tuple;
 	u_short buf[128];
 	cisparse_t parse;
@@ -631,7 +632,8 @@ void serial_config(dev_link_t * link)
  cs_failed:
 	cs_error(link->handle, last_fn, last_ret);
  failed:
-	do_serial_release(info);
+	serial_remove(link);
+	link->state &= ~DEV_CONFIG_PENDING;
 }
 
 /*======================================================================
@@ -647,7 +649,7 @@ static int
 serial_event(event_t event, int priority, event_callback_args_t * args)
 {
 	dev_link_t *link = args->client_data;
-	serial_info_t *info = link->priv;
+	struct serial_info *info = link->priv;
 
 	DEBUG(1, "serial_event(0x%06x)\n", event);
 
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index ab19af68c41b2d485c117c659619647741552b33..98bb4fc127dcf5f6e2921e17f858a9f09c0a6fb3 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -80,14 +80,14 @@ config SERIAL_8250_CS
 config SERIAL_8250_ACPI
 	bool "8250/16550 device discovery via ACPI namespace"
 	default y if IA64
-	depends on ACPI_BUS
+	depends on ACPI_BUS && SERIAL_8250
 	---help---
 	  If you wish to enable serial port discovery via the ACPI
 	  namespace, say Y here.  If unsure, say N.
 
 config SERIAL_8250_HCDP
 	bool "8250/16550 device discovery support via EFI HCDP table"
-	depends on IA64
+	depends on IA64 && SERIAL_8250
 	---help---
 	  If you wish to make the serial console port described by the EFI
 	  HCDP table available for use as serial console or general