public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] pcxx: replace cli()/sti() with spin_lock_irqsave()/spin_unlock_irqrestore()
@ 2004-12-17 22:34 James Nelson
  2004-12-20 14:59 ` Alan Cox
  0 siblings, 1 reply; 5+ messages in thread
From: James Nelson @ 2004-12-17 22:34 UTC (permalink / raw)
  To: kernel-janitors, linux-kernel; +Cc: akpm, James Nelson

This is an attempt to make the pcxx driver SMP-correct.

Compile tested.

Signed-off-by: James Nelson <james4765@gmail.com>

diff -urN --exclude='*~' linux-2.6.10-rc3-mm1-original/drivers/char/Kconfig linux-2.6.10-rc3-mm1/drivers/char/Kconfig
--- linux-2.6.10-rc3-mm1-original/drivers/char/Kconfig	2004-12-03 16:52:14.000000000 -0500
+++ linux-2.6.10-rc3-mm1/drivers/char/Kconfig	2004-12-17 16:52:48.983563961 -0500
@@ -157,7 +157,7 @@
 
 config DIGI
 	tristate "Digiboard PC/Xx Support"
-	depends on SERIAL_NONSTANDARD && DIGIEPCA=n && BROKEN_ON_SMP
+	depends on SERIAL_NONSTANDARD && DIGIEPCA=n
 	help
 	  This is a driver for the Digiboard PC/Xe, PC/Xi, and PC/Xeve cards
 	  that give you many serial ports. You would need something like this
diff -urN --exclude='*~' linux-2.6.10-rc3-mm1-original/drivers/char/pcxx.c linux-2.6.10-rc3-mm1/drivers/char/pcxx.c
--- linux-2.6.10-rc3-mm1-original/drivers/char/pcxx.c	2004-12-03 16:53:57.000000000 -0500
+++ linux-2.6.10-rc3-mm1/drivers/char/pcxx.c	2004-12-17 17:07:03.200241656 -0500
@@ -101,6 +101,8 @@
 static int verbose = 0;
 static int debug   = 0;
 
+static spinlock_t pcxx_lock = SPIN_LOCK_UNLOCKED;
+
 #ifdef MODULE
 /* Variables for insmod */
 static int io[]           = {0, 0, 0, 0};
@@ -209,8 +211,7 @@
 
 	printk(KERN_NOTICE "Unloading PC/Xx version %s\n", VERSION);
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&pcxx_lock, flags);
 	del_timer_sync(&pcxx_timer);
 
 	if ((e1 = tty_unregister_driver(pcxe_driver)))
@@ -219,7 +220,7 @@
 	put_tty_driver(pcxe_driver);
 	cleanup_board_resources();
 	kfree(digi_channels);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&pcxx_lock, flags);
 }
 
 static inline struct channel *chan(register struct tty_struct *tty)
@@ -323,12 +324,12 @@
 	info->blocked_open++;
 
 	for (;;) {
-		cli();
+		spin_lock_irq(&pcxx_lock);
 		globalwinon(info);
 		info->omodem |= DTR|RTS;
 		fepcmd(info, SETMODEM, DTR|RTS, 0, 10, 1);
 		memoff(info);
-		sti();
+		spin_unlock_irq(&pcxx_lock);
 		set_current_state(TASK_INTERRUPTIBLE);
 		if(tty_hung_up_p(filp) || (info->asyncflags & ASYNC_INITIALIZED) == 0) {
 			if(info->asyncflags & ASYNC_HUP_NOTIFY)
@@ -404,8 +405,7 @@
 			return -ERESTARTSYS;
 	}
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&pcxx_lock, flags);
 	ch->count++;
 	tty->driver_data = ch;
 	ch->tty = tty;
@@ -428,7 +428,7 @@
 		memoff(ch);
 		ch->asyncflags |= ASYNC_INITIALIZED;
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&pcxx_lock, flags);
 
 	if(ch->asyncflags & ASYNC_CLOSING) {
 		interruptible_sleep_on(&ch->close_wait);
@@ -463,8 +463,7 @@
 	if (!(info->asyncflags & ASYNC_INITIALIZED)) 
 		return;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&pcxx_lock, flags);
 	globalwinon(info);
 
 	bc = info->brdchan;
@@ -483,7 +482,7 @@
 
 	memoff(info);
 	info->asyncflags &= ~ASYNC_INITIALIZED;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&pcxx_lock, flags);
 }
 
 
@@ -493,8 +492,7 @@
 
 	if ((info=chan(tty))!=NULL) {
 		unsigned long flags;
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&pcxx_lock, flags);
 
 		if(tty_hung_up_p(filp)) {
 			/* flag that somebody is done with this module */
@@ -544,7 +542,7 @@
 		}
 		info->asyncflags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
 		wake_up_interruptible(&info->close_wait);
-		restore_flags(flags);
+		spin_unlock_irqrestore(&pcxx_lock, flags);
 	}
 }
 
@@ -556,15 +554,14 @@
 	if ((ch=chan(tty))!=NULL) {
 		unsigned long flags;
 
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&pcxx_lock, flags);
 		shutdown(ch);
 		ch->event = 0;
 		ch->count = 0;
 		ch->tty = NULL;
 		ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
 		wake_up_interruptible(&ch->open_wait);
-		restore_flags(flags);
+		spin_unlock_irqrestore(&pcxx_lock, flags);
 	}
 }
 
@@ -590,8 +587,7 @@
 	 */
 
 	total = 0;
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&pcxx_lock, flags);
 	globalwinon(ch);
 	head = bc->tin & (size - 1);
 	tail = bc->tout;
@@ -629,7 +625,7 @@
 		bc->ilow = 1;
 	}
 	memoff(ch);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&pcxx_lock, flags);
 	
 	return(total);
 }
@@ -653,8 +649,7 @@
 		unsigned int head, tail;
 		unsigned long flags;
 
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&pcxx_lock, flags);
 		globalwinon(ch);
 
 		bc = ch->brdchan;
@@ -672,7 +667,7 @@
 			bc->ilow = 1;
 		}
 		memoff(ch);
-		restore_flags(flags);
+		spin_unlock_irqrestore(&pcxx_lock, flags);
 	}
 
 	return remain;
@@ -691,8 +686,7 @@
 	if ((ch=chan(tty))==NULL)
 		return(0);
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&pcxx_lock, flags);
 	globalwinon(ch);
 
 	bc = ch->brdchan;
@@ -718,7 +712,7 @@
 	}
 
 	memoff(ch);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&pcxx_lock, flags);
 
 	return(chars);
 }
@@ -734,8 +728,7 @@
 	if ((ch=chan(tty))==NULL)
 		return;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&pcxx_lock, flags);
 
 	globalwinon(ch);
 	bc = ch->brdchan;
@@ -743,7 +736,7 @@
 	fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0);
 
 	memoff(ch);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&pcxx_lock, flags);
 
 	tty_wakeup(tty);
 }
@@ -755,11 +748,10 @@
 	if ((ch=chan(tty))!=NULL) {
 		unsigned long flags;
 
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&pcxx_lock, flags);
 		if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT))
 			setup_empty_event(tty,ch);
-		restore_flags(flags);
+		spin_unlock_irqrestore(&pcxx_lock, flags);
 	}
 }
 
@@ -1512,8 +1504,7 @@
 	struct channel *ch;
 	struct board_info *bd;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&pcxx_lock, flags);
 
 	for(crd=0; crd < numcards; crd++) {
 		bd = &boards[crd];
@@ -1536,7 +1527,7 @@
 	}
 
 	mod_timer(&pcxx_timer, jiffies + HZ/25);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&pcxx_lock, flags);
 }
 
 static void doevent(int crd)
@@ -1940,12 +1931,11 @@
 		return(-EINVAL);
 	}
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&pcxx_lock, flags);
 	globalwinon(ch);
 	mstat = bc->mstat;
 	memoff(ch);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&pcxx_lock, flags);
 
 	if(mstat & DTR)
 		mflag |= TIOCM_DTR;
@@ -1978,8 +1968,7 @@
 		return(-EINVAL);
 	}
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&pcxx_lock, flags);
 	/*
 	 * I think this modemfake stuff is broken.  It doesn't
 	 * correctly reflect the behaviour desired by the TIOCM*
@@ -2005,7 +1994,7 @@
 	globalwinon(ch);
 	pcxxparam(tty,ch);
 	memoff(ch);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&pcxx_lock, flags);
 	return 0;
 }
 
@@ -2028,7 +2017,6 @@
 		return(-EINVAL);
 	}
 
-	save_flags(flags);
 
 	switch(cmd) {
 		case TCSBRK:	/* SVID version: non-zero arg --> no break */
@@ -2074,21 +2062,21 @@
 			return pcxe_tiocmset(tty, file, mstat, ~mstat);
 
 		case TIOCSDTR:
-			cli();
+			spin_lock_irqsave(&pcxx_lock, flags);
 			ch->omodem |= DTR;
 			globalwinon(ch);
 			fepcmd(ch, SETMODEM, DTR, 0, 10, 1);
 			memoff(ch);
-			restore_flags(flags);
+			spin_unlock_irqrestore(&pcxx_lock, flags);
 			break;
 
 		case TIOCCDTR:
 			ch->omodem &= ~DTR;
-			cli();
+			spin_lock_irqsave(&pcxx_lock, flags);
 			globalwinon(ch);
 			fepcmd(ch, SETMODEM, 0, DTR, 10, 1);
 			memoff(ch);
-			restore_flags(flags);
+			spin_unlock_irqrestore(&pcxx_lock, flags);
 			break;
 
 		case DIGI_GETA:
@@ -2123,16 +2111,16 @@
 				ch->dsr = DSR;
 			}
 		
-			cli();
+			spin_lock_irqsave(&pcxx_lock, flags);
 			globalwinon(ch);
 			pcxxparam(tty,ch);
 			memoff(ch);
-			restore_flags(flags);
+			spin_unlock_irqrestore(&pcxx_lock, flags);
 			break;
 
 		case DIGI_GETFLOW:
 		case DIGI_GETAFLOW:
-			cli();	
+			spin_lock_irqsave(&pcxx_lock, flags);
 			globalwinon(ch);
 			if(cmd == DIGI_GETFLOW) {
 				dflow.startc = bc->startc;
@@ -2142,7 +2130,7 @@
 				dflow.stopc = bc->stopca;
 			}
 			memoff(ch);
-			restore_flags(flags);
+			spin_unlock_irqrestore(&pcxx_lock, flags);
 
 			if (copy_to_user((char*)arg, &dflow, sizeof(dflow)))
 				return -EFAULT;
@@ -2162,7 +2150,7 @@
 				return -EFAULT;
 
 			if(dflow.startc != startc || dflow.stopc != stopc) {
-				cli();
+				spin_lock_irqsave(&pcxx_lock, flags);
 				globalwinon(ch);
 
 				if(cmd == DIGI_SETFLOW) {
@@ -2179,7 +2167,7 @@
 					pcxe_start(tty);
 
 				memoff(ch);
-				restore_flags(flags);
+				spin_unlock_irqrestore(&pcxx_lock, flags);
 			}
 			break;
 
@@ -2196,8 +2184,7 @@
 
 	if ((info=chan(tty))!=NULL) {
 		unsigned long flags;
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&pcxx_lock, flags);
 		globalwinon(info);
 		pcxxparam(tty,info);
 		memoff(info);
@@ -2208,7 +2195,7 @@
 		if(!(old_termios->c_cflag & CLOCAL) &&
 			(tty->termios->c_cflag & CLOCAL))
 			wake_up_interruptible(&info->open_wait);
-		restore_flags(flags);
+		spin_unlock_irqrestore(&pcxx_lock, flags);
 	}
 }
 
@@ -2237,15 +2224,14 @@
 
 	if ((info=chan(tty))!=NULL) {
 		unsigned long flags;
-		save_flags(flags); 
-		cli();
+		spin_lock_irqsave(&pcxx_lock, flags);
 		if ((info->statusflags & TXSTOPPED) == 0) {
 			globalwinon(info);
 			fepcmd(info, PAUSETX, 0, 0, 0, 0);
 			info->statusflags |= TXSTOPPED;
 			memoff(info);
 		}
-		restore_flags(flags);
+		spin_unlock_irqrestore(&pcxx_lock, flags);
 	}
 }
 
@@ -2255,15 +2241,14 @@
 
 	if ((info=chan(tty))!=NULL) {
 		unsigned long flags;
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&pcxx_lock, flags);
 		if ((info->statusflags & RXSTOPPED) == 0) {
 			globalwinon(info);
 			fepcmd(info, PAUSERX, 0, 0, 0, 0);
 			info->statusflags |= RXSTOPPED;
 			memoff(info);
 		}
-		restore_flags(flags);
+		spin_unlock_irqrestore(&pcxx_lock, flags);
 	}
 }
 
@@ -2275,8 +2260,7 @@
 		unsigned long flags;
 
 		/* Just in case output was resumed because of a change in Digi-flow */
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&pcxx_lock, flags);
 		if(info->statusflags & RXSTOPPED) {
 			volatile struct board_chan *bc;
 			globalwinon(info);
@@ -2285,7 +2269,7 @@
 			info->statusflags &= ~RXSTOPPED;
 			memoff(info);
 		}
-		restore_flags(flags);
+		spin_unlock_irqrestore(&pcxx_lock, flags);
 	}
 }
 
@@ -2297,8 +2281,7 @@
 	if ((info=chan(tty))!=NULL) {
 		unsigned long flags;
 
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&pcxx_lock, flags);
 		/* Just in case output was resumed because of a change in Digi-flow */
 		if(info->statusflags & TXSTOPPED) {
 			volatile struct board_chan *bc;
@@ -2310,7 +2293,7 @@
 			info->statusflags &= ~TXSTOPPED;
 			memoff(info);
 		}
-		restore_flags(flags);
+		spin_unlock_irqrestore(&pcxx_lock, flags);
 	}
 }
 
@@ -2319,8 +2302,7 @@
 {
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&pcxx_lock, flags);
 	globalwinon(ch);
 
 	/* 
@@ -2334,7 +2316,7 @@
 	fepcmd(ch, SENDBREAK, msec, 0, 10, 0);
 	memoff(ch);
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&pcxx_lock, flags);
 }
 
 static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
@@ -2342,12 +2324,11 @@
 	volatile struct board_chan *bc;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&pcxx_lock, flags);
 	globalwinon(ch);
 	ch->statusflags |= EMPTYWAIT;
 	bc = ch->brdchan;
 	bc->iempty = 1;
 	memoff(ch);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&pcxx_lock, flags);
 }

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2004-12-20 21:51 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-12-17 22:34 [PATCH] pcxx: replace cli()/sti() with spin_lock_irqsave()/spin_unlock_irqrestore() James Nelson
2004-12-20 14:59 ` Alan Cox
2004-12-20 17:27   ` [KJ] " Matthew Wilcox
2004-12-20 20:23   ` Alan Cox
2004-12-20 21:51     ` Jim Nelson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox