RIO
PATCH 1/1 RIO
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.
Patrick
drivers/char/Kconfig +1 -1
@@ -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
drivers/char/rio/linux_compat.h +2 -2
@@ -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))
drivers/char/rio/rio_linux.c +16 -7
@@ -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 ;
drivers/char/rio/riotty.c +14 -4
@@ -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 ) {
Quoted 29 lines · Patrick van de Lageweg
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 <[email protected]>Signed-off-by Rogier Wolff <[email protected]>Patrick
diff -u -r linux-2.6.10-rc3-clean/drivers/char/Kconfig linux-2.6.10-rc3-rio/drivers/char/Kconfig
drivers/char/Kconfig +1
-1@@ -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. Productdiff -u -r
linux-2.6.10-rc3-clean/drivers/char/rio/linux_compat.hlinux-2.6.10-rc3-rio/drivers/char/rio/linux_compat.h
drivers/char/rio/linux_compat.h line 23
Quoted 7 lines
drivers/char/rio/linux_compat.h +2
-2@@ -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) ;
This looks broken. local_irq_* really isn't for driver use except for exception case. Also please kill such silly wrappers..
drivers/char/rio/linux_compat.h line 26
Quoted 3 lines
drivers/char/rio/linux_compat.h +0
-0#define sysbrk (x) kmalloc ((x),in_interrupt()? GFP_ATOMIC : GFP_KERNEL)#define sysfree (p,size) kfree ((p))
dito here. Also the in_interrupt() check is wrong.
Looking at the driver with it's deep mess and K&R prototypes you might be better off with a start from scratch.