From: Patrick van de Lageweg 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 Signed-off-by: Rogier Wolff Signed-off-by: Andrew Morton --- 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 -#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) { _