
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 "rio" 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/rio/linux_compat.h |    4 ++--
 25-akpm/drivers/char/rio/rio_linux.c    |   23 ++++++++++++++++-------
 25-akpm/drivers/char/rio/riotty.c       |   16 +++++++++++++---
 4 files changed, 32 insertions(+), 13 deletions(-)

diff -puN drivers/char/Kconfig~rio-cli-conversion drivers/char/Kconfig
--- 25/drivers/char/Kconfig~rio-cli-conversion	2005-01-05 15:43:27.572544664 -0800
+++ 25-akpm/drivers/char/Kconfig	2005-01-05 15:43:39.735695584 -0800
@@ -299,7 +299,7 @@ config SX
 
 config RIO
 	tristate "Specialix RIO system support"
-	depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+	depends on SERIAL_NONSTANDARD
 	help
 	  This is a driver for the Specialix RIO, a smart serial card which
 	  drives an outboard box that can support up to 128 ports.  Product
diff -puN drivers/char/rio/linux_compat.h~rio-cli-conversion drivers/char/rio/linux_compat.h
--- 25/drivers/char/rio/linux_compat.h~rio-cli-conversion	2005-01-05 15:43:27.573544512 -0800
+++ 25-akpm/drivers/char/rio/linux_compat.h	2005-01-05 15:43:27.581543296 -0800
@@ -19,8 +19,8 @@
 #include <linux/interrupt.h>
 
 
-#define disable(oldspl) save_flags (oldspl)
-#define restore(oldspl) restore_flags (oldspl)
+#define disable(oldspl) local_irq_save(oldspl);
+#define restore(oldspl) local_irq_restore(oldspl) ;
 
 #define sysbrk(x) kmalloc ((x),in_interrupt()? GFP_ATOMIC : GFP_KERNEL)
 #define sysfree(p,size) kfree ((p))
diff -puN drivers/char/rio/rio_linux.c~rio-cli-conversion drivers/char/rio/rio_linux.c
--- 25/drivers/char/rio/rio_linux.c~rio-cli-conversion	2005-01-05 15:43:27.575544208 -0800
+++ 25-akpm/drivers/char/rio/rio_linux.c	2005-01-05 15:43:27.583542992 -0800
@@ -354,7 +354,7 @@ int RIODelay_ni (struct Port *PortP, int
 
 int rio_minor(struct tty_struct *tty)
 {
-	return tty->index + (tty->driver == rio_driver) ? 0 : 256;
+	return tty->index + ((tty->driver == rio_driver) ? 0 : 256);
 }
 
 
@@ -405,6 +405,8 @@ void rio_reset_interrupt (struct Host *H
 static irqreturn_t rio_interrupt (int irq, void *ptr, struct pt_regs *regs)
 {
   struct Host *HostP;
+  int old_debug=rio_debug;
+  rio_debug=0;
   func_enter ();
 
   HostP = (struct Host*)ptr; /* &p->RIOHosts[(long)ptr]; */
@@ -458,12 +460,14 @@ static irqreturn_t rio_interrupt (int ir
     rio_reset_interrupt (HostP);
   }
 
-  if ((HostP->Flags & RUN_STATE) != RC_RUNNING)
+  if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
+          rio_debug=old_debug;
   	return IRQ_HANDLED;
-
+  }
   if (test_and_set_bit (RIO_BOARD_INTR_LOCK, &HostP->locks)) {
     printk (KERN_ERR "Recursive interrupt! (host %d/irq%d)\n", 
             (int) ptr, HostP->Ivec);
+    rio_debug=old_debug;
     return IRQ_HANDLED;
   }
 
@@ -476,6 +480,7 @@ static irqreturn_t rio_interrupt (int ir
   rio_dprintk (RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", 
                irq, HostP->Ivec); 
   func_exit ();
+rio_debug=old_debug;
   return IRQ_HANDLED;
 }
 
@@ -726,6 +731,9 @@ static int rio_ioctl (struct tty_struct 
       rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg);
     break;
 #if 0
+    /* As far as we know this is impossible -- PVDL */
+
+
   /*
    * note: these IOCTLs no longer reach here.  Use
    * tiocmset/tiocmget driver methods instead.  The
@@ -980,6 +988,7 @@ static int rio_init_datastructures (void
     port->gs.closing_wait = 30 * HZ;
     port->gs.rd = &rio_real_driver;
     port->portSem = SPIN_LOCK_UNLOCKED;
+    port->gs.driver_lock = SPIN_LOCK_UNLOCKED;
     /*
      * Initializing wait queue
      */
@@ -1048,7 +1057,7 @@ static void  __exit rio_release_drivers(
 void fix_rio_pci (struct pci_dev *pdev)
 {
   unsigned int hwbase;
-  unsigned long rebase;
+  char *rebase;
   unsigned int t;
 
 #define CNTRL_REG_OFFSET        0x50
@@ -1056,7 +1065,7 @@ void fix_rio_pci (struct pci_dev *pdev)
 
   pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
   hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
-  rebase =  (ulong) ioremap(hwbase, 0x80);
+  rebase =  ioremap(hwbase, 0x80);
   t = readl (rebase + CNTRL_REG_OFFSET);
   if (t != CNTRL_REG_GOODVALUE) {
     printk (KERN_DEBUG "rio: performing cntrl reg fix: %08x -> %08x\n", 
@@ -1137,7 +1146,7 @@ static int __init rio_init(void) 
       if (((1 << hp->Ivec) & rio_irqmask) == 0)
               hp->Ivec = 0;
       hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
-      hp->CardP	= (struct DpRam *) hp->Caddr;
+      hp->CardP = (struct DpRam *) hp->Caddr;
       hp->Type  = RIO_PCI;
       hp->Copy  = rio_pcicopy; 
       hp->Mode  = RIO_PCI_BOOT_FROM_RAM;
@@ -1195,7 +1204,7 @@ static int __init rio_init(void) 
       	hp->Ivec = 0;
       hp->Ivec |= 0x8000; /* Mark as non-sharable */
       hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
-      hp->CardP	= (struct DpRam *) hp->Caddr;
+      hp->CardP = (struct DpRam *) hp->Caddr;
       hp->Type  = RIO_PCI;
       hp->Copy  = rio_pcicopy;
       hp->Mode  = RIO_PCI_BOOT_FROM_RAM;
diff -puN drivers/char/rio/riotty.c~rio-cli-conversion drivers/char/rio/riotty.c
--- 25/drivers/char/rio/riotty.c~rio-cli-conversion	2005-01-05 15:43:27.577543904 -0800
+++ 25-akpm/drivers/char/rio/riotty.c	2005-01-05 15:43:27.584542840 -0800
@@ -203,6 +203,9 @@ riotopen(struct tty_struct * tty, struct
 
 	tty->driver_data = PortP;
 
+	if (PortP->gs.flags & ASYNC_CLOSING){
+		interruptible_sleep_on(&PortP->gs.close_wait);
+	}
 	PortP->gs.tty = tty;
 	PortP->gs.count++;
 
@@ -408,6 +411,7 @@ riotopen(struct tty_struct * tty, struct
 bombout:
 		  /* 			RIOClearUp( PortP ); */
 			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			func_exit ();
 			return retval;
 		}
 		rio_dprintk (RIO_DEBUG_TTY, "PORT_ISOPEN found\n");
@@ -458,15 +462,19 @@ bombout:
 					*/
 					rio_dprintk (RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n",
 					       SysPort);
-					RIOPreemptiveCmd( p, PortP, FCLOSE );
+
+					// Do not close port on RTA if the port	has multiple opens.
+					if( PortP->gs.count <= 1 )
+						RIOPreemptiveCmd( p, PortP, FCLOSE );
+
 					/*
 					tp->tm.c_state &= ~WOPEN;
 					*/
 					PortP->State &= ~RIO_WOPEN;
-					rio_spin_unlock_irqrestore(&PortP->portSem, flags);
 					func_exit ();
 					return -EINTR;
 				}
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
 			}
 			PortP->State &= ~RIO_WOPEN;
 		}
@@ -525,7 +533,7 @@ riotclose(void  *ptr)
 	int	try = -1; /* Disable the timeouts by setting them to -1 */
 	int	repeat_this = -1; /* Congrats to those having 15 years of 
 				     uptime! (You get to break the driver.) */
-	long end_time;
+	unsigned long end_time;
 	struct tty_struct * tty;
 	unsigned long flags;
 	int Modem;
@@ -659,6 +667,7 @@ riotclose(void  *ptr)
 
 	if (RIOShortCommand(p, PortP, CLOSE, 1, 0) == RIO_FAIL) {
 	  RIOPreemptiveCmd(p, PortP,FCLOSE);
+	  rio_spin_lock_irqsave(&PortP->portSem, flags);
 	  goto close_end;
 	}
 
@@ -675,6 +684,7 @@ riotclose(void  *ptr)
 
 		if ( p->RIOHalted ) {
 			RIOClearUp( PortP );
+			rio_spin_lock_irqsave(&PortP->portSem, flags);
 			goto close_end;
 		}
 		if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
_
