Skip to contentSkip to conversation

generic-serial

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 generic-serial

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 prepares the way for the "io8+", "sx" and "rio" drivers to become SMP safe. Patches for those drivers follow.

Patrick

drivers/char/generic_serial.c +65 -50
diff -u -r linux-2.6.10-rc3-clean/drivers/char/generic_serial.c linux-2.6.10-rc3-generix-serial/drivers/char/generic_serial.c
@@ -26,6 +26,7 @@
 #include <linux/mm.h>
 #include <linux/generic_serial.h>
 #include <linux/interrupt.h>
+#include <linux/tty_flip.h>
 #include <linux/delay.h>
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
@@ -45,8 +46,8 @@
 
 #define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __FUNCTION__)
 #define func_exit()  gs_dprintk (GS_DEBUG_FLOW, "gs: exit  %s\n", __FUNCTION__)
-
-#ifdef NEW_WRITE_LOCKING
+#define NEW_WRITE_LOCKING 1
+#if NEW_WRITE_LOCKING
 #define DECL      /* Nothing */
 #define LOCKIT    down (& port->port_write_sem);
 #define RELEASEIT up (&port->port_write_sem);
@@ -208,7 +209,7 @@
 	if (!port || !port->xmit_buf || !tmp_buf)
 		return -EIO;
 
-	save_flags(flags);
+	local_save_flags(flags);
 	while (1) {
 		cli();
 		c = count;
@@ -227,14 +228,14 @@
 
 		/* Can't copy more? break out! */
 		if (c <= 0) {
-			restore_flags(flags);
+			local_restore_flags(flags);
 			break;
 		}
 		memcpy(port->xmit_buf + port->xmit_head, buf, c);
 		port->xmit_head = ((port->xmit_head + c) &
 		                   (SERIAL_XMIT_SIZE-1));
 		port->xmit_cnt += c;
-		restore_flags(flags);
+		local_restore_flags(flags);
 		buf += c;
 		count -= c;
 		total += c;
@@ -380,9 +381,9 @@
 	if (!port) return;
 
 	/* XXX Would the write semaphore do? */
-	save_flags(flags); cli();
+	spin_lock_irqsave (&port->driver_lock, flags);
 	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	restore_flags(flags);
+	spin_unlock_irqrestore (&port->driver_lock, flags);
 
 	wake_up_interruptible(&tty->write_wait);
 	tty_wakeup(tty);
@@ -468,8 +469,7 @@
 	if (!(port->flags & ASYNC_INITIALIZED))
 		return;
 
-	save_flags (flags);
-	cli ();
+	spin_lock_irqsave(&port->driver_lock, flags);
 
 	if (port->xmit_buf) {
 		free_page((unsigned long) port->xmit_buf);
@@ -482,7 +482,7 @@
 	port->rd->shutdown_port (port);
 
 	port->flags &= ~ASYNC_INITIALIZED;
-	restore_flags (flags);
+	spin_unlock_irqrestore(&port->driver_lock, flags);
 
 	func_exit();
 }
@@ -540,6 +540,7 @@
 	int    do_clocal = 0;
 	int    CD;
 	struct tty_struct *tty;
+	unsigned long flags;
 
 	func_enter ();
 
@@ -591,10 +592,11 @@
 	add_wait_queue(&port->open_wait, &wait);
 
 	gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); 
-	cli();
-	if (!tty_hung_up_p(filp))
+	spin_lock_irqsave(&port->driver_lock, flags);
+	if (!tty_hung_up_p(filp)) {
 		port->count--;
-	sti();
+	}
+	spin_unlock_irqrestore(&port->driver_lock, flags);
 	port->blocked_open++;
 	while (1) {
 		CD = port->rd->get_CD (port);
@@ -623,8 +625,9 @@
 		    port->blocked_open);
 	set_current_state (TASK_RUNNING);
 	remove_wait_queue(&port->open_wait, &wait);
-	if (!tty_hung_up_p(filp))
+	if (!tty_hung_up_p(filp)) {
 		port->count++;
+	}
 	port->blocked_open--;
 	if (retval)
 		return retval;
@@ -654,27 +657,29 @@
 		port->tty = tty;
 	}
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&port->driver_lock, flags);
 
 	if (tty_hung_up_p(filp)) {
-		restore_flags(flags);
-		port->rd->hungup (port);
+		spin_unlock_irqrestore(&port->driver_lock, flags);
+		if (port->rd->hungup) 
+			port->rd->hungup (port);
 		func_exit ();
 		return;
 	}
 
 	if ((tty->count == 1) && (port->count != 1)) {
-		printk(KERN_ERR "gs: gs_close: bad port count;"
-		       " tty->count is 1, port count is %d\n", port->count);
+		printk(KERN_ERR "gs: gs_close port %p: bad port count;"
+		       " tty->count is 1, port count is %d\n", port, port->count);
 		port->count = 1;
 	}
 	if (--port->count < 0) {
-		printk(KERN_ERR "gs: gs_close: bad port count: %d\n", port->count);
+		printk(KERN_ERR "gs: gs_close port %p: bad port count: %d\n", port, port->count);
 		port->count = 0;
 	}
+
 	if (port->count) {
-		gs_dprintk(GS_DEBUG_CLOSE, "gs_close: count: %d\n", port->count);
-		restore_flags(flags);
+		gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->count);
+		spin_unlock_irqrestore(&port->driver_lock, flags);
 		func_exit ();
 		return;
 	}
@@ -696,16 +701,17 @@
 	 */
 
 	port->rd->disable_rx_interrupts (port);
+	spin_unlock_irqrestore(&port->driver_lock, flags);
 
 	/* close has no way of returning "EINTR", so discard return value */
 	if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-		gs_wait_tx_flushed (port, port->closing_wait); 
+		gs_wait_tx_flushed (port, port->closing_wait);
 
 	port->flags &= ~GS_ACTIVE;
 
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-		
+
 	tty_ldisc_flush(tty);
 	tty->closing = 0;
 
@@ -716,14 +722,15 @@
 
 	if (port->blocked_open) {
 		if (port->close_delay) {
+			spin_unlock_irqrestore(&port->driver_lock, flags);
 			msleep_interruptible(jiffies_to_msecs(port->close_delay));
+			spin_lock_irqsave(&port->driver_lock, flags);
 		}
 		wake_up_interruptible(&port->open_wait);
 	}
 	port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING | ASYNC_INITIALIZED);
 	wake_up_interruptible(&port->close_wait);
 
-	restore_flags(flags);
 	func_exit ();
 }
 
@@ -748,6 +755,12 @@
 	port = tty->driver_data;
 
 	if (!port) return;
+	if (!port->tty) {
+		/* This seems to happen when this is called after gs_close. */
+		gs_dprintk (GS_DEBUG_TERMIOS, "gs: Odd: port->tty is NULL\n");
+		port->tty = tty;
+	}
+	
 
 	tiosp = tty->termios;
 
@@ -842,7 +855,7 @@
 
 	if (!(old_termios->c_cflag & CLOCAL) &&
 	    (tty->termios->c_cflag & CLOCAL))
-		wake_up_interruptible(&info->open_wait);
+		wake_up_interruptible(&port->gs.open_wait);
 #endif
 
 	func_exit();
@@ -857,56 +870,56 @@
 	unsigned long flags;
 	unsigned long page;
 
-	save_flags (flags);
-	if (!tmp_buf) {
-		page = get_zeroed_page(GFP_KERNEL);
+	func_enter ();
 
-		cli (); /* Don't expect this to make a difference. */ 
+        if (!tmp_buf) {
+		page = get_zeroed_page(GFP_KERNEL);
+		spin_lock_irqsave (&port->driver_lock, flags); /* Don't expect this to make a difference. */ 
 		if (tmp_buf)
 			free_page(page);
 		else
 			tmp_buf = (unsigned char *) page;
-		restore_flags (flags);
-
+		spin_unlock_irqrestore (&port->driver_lock, flags);
 		if (!tmp_buf) {
+			func_exit ();
 			return -ENOMEM;
 		}
 	}
 
-	if (port->flags & ASYNC_INITIALIZED)
+	if (port->flags & ASYNC_INITIALIZED) {
+		func_exit ();
 		return 0;
-
+	}
 	if (!port->xmit_buf) {
 		/* We may sleep in get_zeroed_page() */
 		unsigned long tmp;
 
 		tmp = get_zeroed_page(GFP_KERNEL);
-
-		/* Spinlock? */
-		cli ();
+		spin_lock_irqsave (&port->driver_lock, flags);
 		if (port->xmit_buf) 
 			free_page (tmp);
 		else
 			port->xmit_buf = (unsigned char *) tmp;
-		restore_flags (flags);
-
-		if (!port->xmit_buf)
+		spin_unlock_irqrestore(&port->driver_lock, flags);
+		if (!port->xmit_buf) {
+			func_exit ();
 			return -ENOMEM;
+		}
 	}
 
-	cli();
-
+	spin_lock_irqsave (&port->driver_lock, flags);
 	if (port->tty) 
 		clear_bit(TTY_IO_ERROR, &port->tty->flags);
-
+	init_MUTEX(&port->port_write_sem);
 	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-
+	spin_unlock_irqrestore(&port->driver_lock, flags);
 	gs_set_termios(port->tty, NULL);
-
+	spin_lock_irqsave (&port->driver_lock, flags);
 	port->flags |= ASYNC_INITIALIZED;
 	port->flags &= ~GS_TX_INTEN;
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&port->driver_lock, flags);
+	func_exit ();
 	return 0;
 }
 
@@ -977,13 +990,15 @@
 
 void gs_got_break(struct gs_port *port)
 {
+	func_enter ();
+
+	tty_insert_flip_char(port->tty, 0, TTY_BREAK);
+	tty_schedule_flip(port->tty);
 	if (port->flags & ASYNC_SAK) {
 		do_SAK (port->tty);
 	}
-	*(port->tty->flip.flag_buf_ptr) = TTY_BREAK;
-	port->tty->flip.flag_buf_ptr++;
-	port->tty->flip.char_buf_ptr++;
-	port->tty->flip.count++;
+
+	func_exit ();
 }
 
 
include/linux/generic_serial.h +3 -1
diff -u -r linux-2.6.10-rc3-clean/include/linux/generic_serial.h linux-2.6.10-rc3-generix-serial/include/linux/generic_serial.h
@@ -34,7 +34,7 @@
   int                     xmit_head;
   int                     xmit_tail;
   int                     xmit_cnt;
-  /*  struct semaphore        port_write_sem; */
+  struct semaphore        port_write_sem;
   int                     flags;
   wait_queue_head_t       open_wait;
   wait_queue_head_t       close_wait;
@@ -49,6 +49,7 @@
   int                     baud_base;
   int                     baud;
   int                     custom_divisor;
+  spinlock_t              driver_lock;
 };
 
 
@@ -70,6 +71,7 @@
 #define GS_DEBUG_STUFF   0x00000008
 #define GS_DEBUG_CLOSE   0x00000010
 #define GS_DEBUG_FLOW    0x00000020
+#define GS_DEBUG_WRITE   0x00000040
 
 
 void gs_put_char(struct tty_struct *tty, unsigned char ch);
#1 lore raw
Quoted 7 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 prepares the way for the "io8+", "sx" and "rio" drivers to become SMP safe. Patches for those drivers follow.

I'd really prefer moving those drivers over to the new serial core framework than sticking more work into that obsolete code.