From: Patrick van de Lageweg <patrick@bitwizard.nl>

This patch converts all save_flags/restore_flags to the new
spin_lock_irqsave/spin_unlock_irqrestore calls, as well as some other 2.6.X
cleanups.  This allows the "sx" driver to become SMP safe.

Signed-off-by: Patrick vd Lageweg <patrick@bitwizard.nl>
Signed-off-by: Rogier Wolff <R.E.Wolff@BitWizard.nl>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/char/Kconfig |    2 -
 25-akpm/drivers/char/sx.c    |   60 ++++++++++++++++++++++++++++---------------
 2 files changed, 41 insertions(+), 21 deletions(-)

diff -puN drivers/char/Kconfig~sx-cli-conversion drivers/char/Kconfig
--- 25/drivers/char/Kconfig~sx-cli-conversion	2005-01-10 21:15:26.729390096 -0800
+++ 25-akpm/drivers/char/Kconfig	2005-01-10 21:15:26.734389336 -0800
@@ -301,7 +301,7 @@ config SPECIALIX_RTSCTS
 
 config SX
 	tristate "Specialix SX (and SI) card support"
-	depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+	depends on SERIAL_NONSTANDARD
 	help
 	  This is a driver for the SX and SI multiport serial cards.
 	  Please read the file <file:Documentation/sx.txt> for details.
diff -puN drivers/char/sx.c~sx-cli-conversion drivers/char/sx.c
--- 25/drivers/char/sx.c~sx-cli-conversion	2005-01-10 21:15:26.730389944 -0800
+++ 25-akpm/drivers/char/sx.c	2005-01-10 21:15:26.737388880 -0800
@@ -4,7 +4,7 @@
  *  This driver will also support the older SI, and XIO cards.
  *
  *
- *   (C) 1998 - 2000  R.E.Wolff@BitWizard.nl
+ *   (C) 1998 - 2004  R.E.Wolff@BitWizard.nl
  *
  *  Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous
  *  version of this driver. Some fragments may have been copied. (none
@@ -354,13 +354,13 @@ static int si1_probe_addrs[]= { 0xd0000}
    Some architectures may need more. */
 static int sx_irqmask = -1;
 
-MODULE_PARM(sx_probe_addrs, "i");
-MODULE_PARM(si_probe_addrs, "i");
-MODULE_PARM(sx_poll, "i");
-MODULE_PARM(sx_slowpoll, "i");
-MODULE_PARM(sx_maxints, "i");
-MODULE_PARM(sx_debug, "i");
-MODULE_PARM(sx_irqmask, "i");
+module_param_array(sx_probe_addrs, int, NULL, 0);
+module_param_array(si_probe_addrs, int, NULL, 0);
+module_param(sx_poll, int, 0);
+module_param(sx_slowpoll, int, 0);
+module_param(sx_maxints, int, 0);
+module_param(sx_debug, int, 0);
+module_param(sx_irqmask, int, 0);
 
 MODULE_LICENSE("GPL");
 
@@ -396,7 +396,7 @@ static struct real_driver sx_real_driver
 
 
 
-#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s\b",__FUNCTION__)
+#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s\n",__FUNCTION__)
 #define func_exit()  sx_dprintk (SX_DEBUG_FLOW, "sx: exit  %s\n", __FUNCTION__)
 
 #define func_enter2() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
@@ -1158,7 +1158,6 @@ static inline void sx_check_modem_signal
 	if (hi_state & ST_BREAK) {
 		hi_state &= ~ST_BREAK;
 		sx_dprintk (SX_DEBUG_MODEMSIGNALS, "got a break.\n");
-
 		sx_write_channel_byte (port, hi_state, hi_state);
 		gs_got_break (&port->gs);
 	}
@@ -1206,7 +1205,7 @@ static irqreturn_t sx_interrupt (int irq
 	struct sx_port *port;
 	int i;
 
-	/*   func_enter ();  */
+	func_enter ();
 	sx_dprintk (SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq, board->irq); 
 
 	/* AAargh! The order in which to do these things is essential and
@@ -1297,7 +1296,7 @@ static irqreturn_t sx_interrupt (int irq
 	clear_bit (SX_BOARD_INTR_LOCK, &board->locks);
 
 	sx_dprintk (SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq, board->irq); 
-	/*  func_exit ();  */
+        func_exit ();
 	return IRQ_HANDLED;
 }
 
@@ -1428,6 +1427,7 @@ static int sx_open  (struct tty_struct *
 {
 	struct sx_port *port;
 	int retval, line;
+	unsigned long flags;
 
 	func_enter();
 
@@ -1449,9 +1449,12 @@ static int sx_open  (struct tty_struct *
 
 	sx_dprintk (SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd);
 
+	spin_lock_irqsave(&port->gs.driver_lock, flags);
+
 	tty->driver_data = port;
 	port->gs.tty = tty;
 	port->gs.count++;
+	spin_unlock_irqrestore(&port->gs.driver_lock, flags);
 
 	sx_dprintk (SX_DEBUG_OPEN, "starting port\n");
 
@@ -1466,7 +1469,8 @@ static int sx_open  (struct tty_struct *
 	}
 
 	port->gs.flags |= GS_ACTIVE;
-	sx_setsignals (port, 1,1);
+	if (port->gs.count <= 1)
+		sx_setsignals (port, 1,1);
 
 #if 0
 	if (sx_debug & SX_DEBUG_OPEN)
@@ -1476,10 +1480,14 @@ static int sx_open  (struct tty_struct *
 		my_hd_io (port->board->base + port->ch_base, sizeof (*port));
 #endif
 
-	if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
-		printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n");
-		port->gs.count--;
-		return -EIO;
+	if (port->gs.count <= 1) {
+		if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
+			printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n");
+			spin_lock_irqsave(&port->gs.driver_lock, flags);
+			port->gs.count--;
+			spin_unlock_irqrestore(&port->gs.driver_lock, flags);
+			return -EIO;
+		}
 	}
 
 	retval = gs_block_til_ready(port, filp);
@@ -1497,6 +1505,7 @@ static int sx_open  (struct tty_struct *
 
 	port->c_dcd = sx_get_CD (port);
 	sx_dprintk (SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
+
 	func_exit();
 	return 0;
 
@@ -1535,7 +1544,8 @@ static void sx_close (void *ptr)
 
 	if(port->gs.count) {
 		sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", port->gs.count);
-		port->gs.count = 0;
+		//printk ("%s SETTING port count to zero: %p count: %d\n", __FUNCTION__, port, port->gs.count);
+		//port->gs.count = 0;
 	}
 
 	func_exit ();
@@ -1751,12 +1761,16 @@ static void sx_break (struct tty_struct 
 	struct sx_port *port = tty->driver_data;
 	int rv;
 
+	func_enter ();
+
 	if (flag) 
 		rv = sx_send_command (port, HS_START, -1, HS_IDLE_BREAK);
 	else 
 		rv = sx_send_command (port, HS_STOP, -1, HS_IDLE_OPEN);
 	if (rv != 1) printk (KERN_ERR "sx: couldn't send break (%x).\n",
 			read_sx_byte (port->board, CHAN_OFFSET (port, hi_hstat)));
+
+	func_exit ();
 }
 
 
@@ -2105,7 +2119,7 @@ static int probe_sx (struct sx_board *bo
 		}
 
 		if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) {
-			if (board->hw_base & 0x8000) {
+			if (((unsigned long)board->hw_base) & 0x8000) {
 				printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %lx.\n", board->hw_base);
 				printk (KERN_WARNING "sx: Read sx.txt for more info.\n");
 			}
@@ -2154,6 +2168,7 @@ static int probe_si (struct sx_board *bo
 	    }
 		for (i=0;i<8;i++) {
 			if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) {
+				func_exit ();
 				return 0;
 			}
 		}
@@ -2168,11 +2183,13 @@ static int probe_si (struct sx_board *bo
 		/* This should be an SI1 board, which has this
 		   location writable... */
 		if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10)
+			func_exit ();
 			return 0; 
 	} else {
 		/* This should be an SI2 board, which has the bottom
 		   3 bits non-writable... */
 		if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10)
+			func_exit ();
 			return 0; 
 	}
 
@@ -2185,11 +2202,13 @@ static int probe_si (struct sx_board *bo
 		/* This should be an SI1 board, which has this
 		   location writable... */
 		if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10)
+			func_exit();
 			return 0; 
 	} else {
 		/* This should be an SI2 board, which has the bottom
 		   3 bits non-writable... */
 		if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10)
+			func_exit ();
 			return 0; 
 	}
 
@@ -2306,6 +2325,7 @@ static int sx_init_portstructs (int nboa
 #ifdef NEW_WRITE_LOCKING
 			port->gs.port_write_sem = MUTEX;
 #endif
+			port->gs.driver_lock = SPIN_LOCK_UNLOCKED;
 			/*
 			 * Initializing wait queue
 			 */
@@ -2477,7 +2497,7 @@ static int __init sx_init(void) 
 			found++;
 			fix_sx_pci (pdev, board);
 		} else 
-			iounmap(board->base);
+			iounmap(board->base2);
 	}
 #endif
 
_