[PATCH] RIO

From: Patrick van de Lageweg
Date: Wed Dec 08 2004 - 08:43:27 EST


Hi,

This patch converts all save_flags/restore_flags to the new
spin_lick_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@xxxxxxxxxxxx>
Signed-off-by: Rogier Wolff <R.E.Wolff@xxxxxxxxxxxx>

Patrick
diff -u -r linux-2.6.10-rc3-clean/drivers/char/Kconfig linux-2.6.10-rc3-rio/drivers/char/Kconfig
--- linux-2.6.10-rc3-clean/drivers/char/Kconfig Fri Dec 3 15:13:32 2004
+++ linux-2.6.10-rc3-rio/drivers/char/Kconfig Fri Dec 3 15:28:48 2004
@@ -299,7 +299,7 @@

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 -u -r linux-2.6.10-rc3-clean/drivers/char/rio/linux_compat.h linux-2.6.10-rc3-rio/drivers/char/rio/linux_compat.h
--- linux-2.6.10-rc3-clean/drivers/char/rio/linux_compat.h Fri Dec 3 15:11:52 2004
+++ linux-2.6.10-rc3-rio/drivers/char/rio/linux_compat.h Fri Dec 3 15:28:48 2004
@@ -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 -u -r linux-2.6.10-rc3-clean/drivers/char/rio/rio_linux.c linux-2.6.10-rc3-rio/drivers/char/rio/rio_linux.c
--- linux-2.6.10-rc3-clean/drivers/char/rio/rio_linux.c Fri Dec 3 15:13:33 2004
+++ linux-2.6.10-rc3-rio/drivers/char/rio/rio_linux.c Fri Dec 3 15:28:48 2004
@@ -354,7 +354,7 @@

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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@

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 @@
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 @@
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 -u -r linux-2.6.10-rc3-clean/drivers/char/rio/riotty.c linux-2.6.10-rc3-rio/drivers/char/rio/riotty.c
--- linux-2.6.10-rc3-clean/drivers/char/rio/riotty.c Sat Aug 14 07:36:56 2004
+++ linux-2.6.10-rc3-rio/drivers/char/rio/riotty.c Fri Dec 3 15:28:48 2004
@@ -202,7 +202,10 @@
}

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 @@
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 @@
*/
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 @@
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 @@

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 @@

if ( p->RIOHalted ) {
RIOClearUp( PortP );
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
goto close_end;
}
if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {