From: Alan Cox <alan@lxorguk.ukuu.org.uk>

Port the driver to the new tty layer and ressurect it to use spinlocks in the
process

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 drivers/char/Kconfig |    2 -
 drivers/char/moxa.c  |   74 ++++++++++++++++++++-------------------------------
 2 files changed, 31 insertions(+), 45 deletions(-)

diff -puN drivers/char/Kconfig~moxa-intellio drivers/char/Kconfig
--- devel/drivers/char/Kconfig~moxa-intellio	2005-09-09 18:29:24.000000000 -0700
+++ devel-akpm/drivers/char/Kconfig	2005-09-09 18:29:24.000000000 -0700
@@ -166,7 +166,7 @@ config ESPSERIAL
 
 config MOXA_INTELLIO
 	tristate "Moxa Intellio support"
-	depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+	depends on SERIAL_NONSTANDARD
 	help
 	  Say Y here if you have a Moxa Intellio multiport serial card.
 
diff -puN drivers/char/moxa.c~moxa-intellio drivers/char/moxa.c
--- devel/drivers/char/moxa.c~moxa-intellio	2005-09-09 18:29:24.000000000 -0700
+++ devel-akpm/drivers/char/moxa.c	2005-09-09 18:29:24.000000000 -0700
@@ -269,7 +269,7 @@ static int MoxaPortDCDChange(int);
 static int MoxaPortDCDON(int);
 static void MoxaPortFlushData(int, int);
 static int MoxaPortWriteData(int, unsigned char *, int);
-static int MoxaPortReadData(int, unsigned char *, int);
+static int MoxaPortReadData(int, struct tty_struct *tty);
 static int MoxaPortTxQueue(int);
 static int MoxaPortRxQueue(int);
 static int MoxaPortTxFree(int);
@@ -301,6 +301,8 @@ static struct tty_operations moxa_ops = 
 	.tiocmset = moxa_tiocmset,
 };
 
+static spinlock_t moxa_lock = SPIN_LOCK_UNLOCKED;
+
 #ifdef CONFIG_PCI
 static int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf * board)
 {
@@ -645,10 +647,10 @@ static int moxa_write(struct tty_struct 
 	if (ch == NULL)
 		return (0);
 	port = ch->port;
-	save_flags(flags);
-	cli();
+
+	spin_lock_irqsave(&moxa_lock, flags);
 	len = MoxaPortWriteData(port, (unsigned char *) buf, count);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&moxa_lock, flags);
 
 	/*********************************************
 	if ( !(ch->statusflags & LOWWAIT) &&
@@ -723,11 +725,10 @@ static void moxa_put_char(struct tty_str
 	if (ch == NULL)
 		return;
 	port = ch->port;
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&moxa_lock, flags);
 	moxaXmitBuff[0] = c;
 	MoxaPortWriteData(port, moxaXmitBuff, 1);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&moxa_lock, flags);
 	/************************************************
 	if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) )
 	*************************************************/
@@ -1030,12 +1031,12 @@ static int block_till_ready(struct tty_s
 	printk("block_til_ready before block: ttys%d, count = %d\n",
 	       ch->line, ch->count);
 #endif
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&moxa_lock, flags);
 	if (!tty_hung_up_p(filp))
 		ch->count--;
-	restore_flags(flags);
 	ch->blocked_open++;
+	spin_unlock_irqrestore(&moxa_lock, flags);
+
 	while (1) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
@@ -1062,17 +1063,21 @@ static int block_till_ready(struct tty_s
 	}
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&ch->open_wait, &wait);
+
+	spin_lock_irqsave(&moxa_lock, flags);
 	if (!tty_hung_up_p(filp))
 		ch->count++;
 	ch->blocked_open--;
+	spin_unlock_irqrestore(&moxa_lock, flags);
 #ifdef SERIAL_DEBUG_OPEN
 	printk("block_til_ready after blocking: ttys%d, count = %d\n",
 	       ch->line, ch->count);
 #endif
 	if (retval)
 		return (retval);
+	/* FIXME: review to see if we need to use set_bit on these */
 	ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
-	return (0);
+	return 0;
 }
 
 static void setup_empty_event(struct tty_struct *tty)
@@ -1080,15 +1085,14 @@ static void setup_empty_event(struct tty
 	struct moxa_str *ch = tty->driver_data;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&moxa_lock, flags);
 	ch->statusflags |= EMPTYWAIT;
 	moxaEmptyTimer_on[ch->port] = 0;
 	del_timer(&moxaEmptyTimer[ch->port]);
 	moxaEmptyTimer[ch->port].expires = jiffies + HZ;
 	moxaEmptyTimer_on[ch->port] = 1;
 	add_timer(&moxaEmptyTimer[ch->port]);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&moxa_lock, flags);
 }
 
 static void check_xmit_empty(unsigned long data)
@@ -1135,8 +1139,6 @@ static void receive_data(struct moxa_str
 {
 	struct tty_struct *tp;
 	struct termios *ts;
-	int i, count, rc, space;
-	unsigned char *charptr, *flagptr;
 	unsigned long flags;
 
 	ts = NULL;
@@ -1150,25 +1152,10 @@ static void receive_data(struct moxa_str
 		MoxaPortFlushData(ch->port, 0);
 		return;
 	}
-	/* Working buffer size */
-	space = tty_buffer_request_room(512);
-	if (space == 0)
-		return;
-	charptr = tp->flip.char_buf_ptr;
-	flagptr = tp->flip.flag_buf_ptr;
-	rc = tp->flip.count;
-	save_flags(flags);
-	cli();
-	count = MoxaPortReadData(ch->port, charptr, space);
-	restore_flags(flags);
-	for (i = 0; i < count; i++)
-		*flagptr++ = 0;
-	charptr += count;
-	rc += count;
-	tp->flip.count = rc;
-	tp->flip.char_buf_ptr = charptr;
-	tp->flip.flag_buf_ptr = flagptr;
-	tty_schedule_flip(ch->tty);
+	spin_lock_irqsave(&moxa_lock, flags);
+	MoxaPortReadData(ch->port, tp);
+	spin_unlock_irqrestore(&moxa_lock, flags);
+	tty_schedule_flip(tp);
 }
 
 #define Magic_code	0x404
@@ -1775,7 +1762,7 @@ int MoxaPortsOfCard(int cardno)
  *	14. MoxaPortDCDON(int port);					     *
  *	15. MoxaPortFlushData(int port, int mode);	                     *
  *	16. MoxaPortWriteData(int port, unsigned char * buffer, int length); *
- *	17. MoxaPortReadData(int port, unsigned char * buffer, int length);  *
+ *	17. MoxaPortReadData(int port, struct tty_struct *tty); 	     *
  *	18. MoxaPortTxBufSize(int port);				     *
  *	19. MoxaPortRxBufSize(int port);				     *
  *	20. MoxaPortTxQueue(int port);					     *
@@ -2004,10 +1991,9 @@ int MoxaPortsOfCard(int cardno)
  *
  *      Function 21:    Read data.
  *      Syntax:
- *      int  MoxaPortReadData(int port, unsigned char * buffer, int length);
+ *      int  MoxaPortReadData(int port, struct tty_struct *tty);
  *           int port           : port number (0 - 127)
- *           unsigned char * buffer     : pointer to read data buffer.
- *           int length         : read data buffer length
+ *	     struct tty_struct *tty : tty for data
  *
  *           return:    0 - length      : real read data length
  *
@@ -2505,7 +2491,7 @@ int MoxaPortWriteData(int port, unsigned
 	return (total);
 }
 
-int MoxaPortReadData(int port, unsigned char * buffer, int space)
+int MoxaPortReadData(int port, struct tty_struct *tty)
 {
 	register ushort head, pageofs;
 	int i, count, cnt, len, total, remain;
@@ -2523,9 +2509,9 @@ int MoxaPortReadData(int port, unsigned 
 	count = (tail >= head) ? (tail - head)
 	    : (tail - head + rx_mask + 1);
 	if (count == 0)
-		return (0);
+		return 0;
 
-	total = (space > count) ? count : space;
+	total = count;
 	remain = count - total;
 	moxaLog.rxcnt[port] += total;
 	count = total;
@@ -2540,7 +2526,7 @@ int MoxaPortReadData(int port, unsigned 
 			len = (count > len) ? len : count;
 			ofs = baseAddr + DynPage_addr + bufhead + head;
 			for (i = 0; i < len; i++)
-				*buffer++ = readb(ofs + i);
+				tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL);
 			head = (head + len) & rx_mask;
 			count -= len;
 		}
@@ -2557,7 +2543,7 @@ int MoxaPortReadData(int port, unsigned 
 			writew(pageno, baseAddr + Control_reg);
 			ofs = baseAddr + DynPage_addr + pageofs;
 			for (i = 0; i < cnt; i++)
-				*buffer++ = readb(ofs + i);
+				tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL);
 			if (count == 0) {
 				writew((head + len) & rx_mask, ofsAddr + RXrptr);
 				break;
_