Skip to contentSkip to conversation

RIO

PATCH In review Patrick van de Lageweg 2 participants 2 messages Dec 8, 2004 Char and misc drivers

lore
Share & tools
lore
#0 lore raw

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
diff -u -r linux-2.6.10-rc3-clean/drivers/char/Kconfig linux-2.6.10-rc3-rio/drivers/char/Kconfig
@@ -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
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
@@ -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
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
@@ -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
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
@@ -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) {
#1 lore raw
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.

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

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.