public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] esp: replace cli()/sti() with spin_lock_irqsave()/spin_unlock_irqrestore()
@ 2004-12-17 23:18 James Nelson
  2004-12-18  1:21 ` Jan Dittmer
  0 siblings, 1 reply; 3+ messages in thread
From: James Nelson @ 2004-12-17 23:18 UTC (permalink / raw)
  To: kernel-janitors, linux-kernel; +Cc: akpm, James Nelson

This is an attempt to make the esp 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/esp.c linux-2.6.10-rc3-mm1/drivers/char/esp.c
--- linux-2.6.10-rc3-mm1-original/drivers/char/esp.c	2004-12-03 16:52:13.000000000 -0500
+++ linux-2.6.10-rc3-mm1/drivers/char/esp.c	2004-12-17 18:11:31.275037730 -0500
@@ -84,6 +84,8 @@
 static unsigned int rx_timeout = ESP_RX_TMOUT;
 static unsigned int pio_threshold = ESP_PIO_THRESHOLD;
 
+static spinlock_t esp_lock = SPIN_LOCK_UNLOCKED;
+
 MODULE_LICENSE("GPL");
 
 module_param_array(irq, int, NULL, 0);
@@ -212,14 +214,14 @@
 	if (serial_paranoia_check(info, tty->name, "rs_stop"))
 		return;
 	
-	save_flags(flags); cli();
+	spin_lock_irqsave(&esp_lock, flags);
 	if (info->IER & UART_IER_THRI) {
 		info->IER &= ~UART_IER_THRI;
 		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
 		serial_out(info, UART_ESI_CMD2, info->IER);
 	}
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&esp_lock, flags);
 }
 
 static void rs_start(struct tty_struct *tty)
@@ -230,13 +232,13 @@
 	if (serial_paranoia_check(info, tty->name, "rs_start"))
 		return;
 	
-	save_flags(flags); cli();
+	spin_lock_irqsave(&esp_lock, flags);
 	if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) {
 		info->IER |= UART_IER_THRI;
 		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
 		serial_out(info, UART_ESI_CMD2, info->IER);
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&esp_lock, flags);
 }
 
 /*
@@ -311,7 +313,7 @@
 		return;
 	}
 
-	sti();
+	spin_unlock_irq(&esp_lock);
 	
 	status_mask = (info->read_status_mask >> 2) & 0x07;
 		
@@ -329,7 +331,7 @@
 			(serial_in(info, UART_ESI_RWS) >> 3) & status_mask;
 	}
 
-	cli();
+	spin_lock_irq(&esp_lock);
 
 	/* make sure everything is still ok since interrupts were enabled */
 	tty = info->tty;
@@ -478,7 +480,7 @@
 		info->xmit_tail = (info->xmit_tail + space_avail) &
 			(ESP_XMIT_SIZE - 1);
 
-		sti();
+		spin_unlock_irq(&esp_lock);
 
 		for (i = 0; i < space_avail - 1; i += 2) {
 			outw(*((unsigned short *)(pio_buf->data + i)),
@@ -489,7 +491,7 @@
 			serial_out(info, UART_ESI_TX,
 				   pio_buf->data[space_avail - 1]);
 
-		cli();
+		spin_lock_irq(&esp_lock);
 
 		if (info->xmit_cnt) {
 			serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
@@ -654,10 +656,10 @@
 	err_status = 0;
 	scratch = serial_in(info, UART_ESI_SID);
 
-	cli();
+	spin_lock_irq(&esp_lock);
 	
 	if (!info->tty) {
-		sti();
+		spin_unlock_irq(&esp_lock);
 		return IRQ_NONE;
 	}
 
@@ -740,7 +742,7 @@
 #ifdef SERIAL_DEBUG_INTR
 	printk("end.\n");
 #endif
-	sti();
+	spin_unlock_irq(&esp_lock);
 	return IRQ_HANDLED;
 }
 
@@ -859,7 +861,7 @@
 	int	retval=0;
         unsigned int num_chars;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&esp_lock, flags);
 
 	if (info->flags & ASYNC_INITIALIZED)
 		goto out;
@@ -973,7 +975,7 @@
 
 	info->flags |= ASYNC_INITIALIZED;
 	retval = 0;
-out:	restore_flags(flags);
+out:	spin_unlock_irqrestore(&esp_lock, flags);
 	return retval;
 }
 
@@ -993,7 +995,7 @@
 	       info->irq);
 #endif
 	
-	save_flags(flags); cli(); /* Disable interrupts */
+	spin_lock_irqsave(&esp_lock, flags); /* Disable interrupts */
 
 	/*
 	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
@@ -1058,7 +1060,7 @@
 		set_bit(TTY_IO_ERROR, &info->tty->flags);
 	
 	info->flags &= ~ASYNC_INITIALIZED;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&esp_lock, flags);
 }
 
 /*
@@ -1172,7 +1174,7 @@
 	if (I_IXOFF(info->tty))
 		flow1 |= 0x81;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&esp_lock, flags);
 	/* set baud */
 	serial_out(info, UART_ESI_CMD1, ESI_SET_BAUD);
 	serial_out(info, UART_ESI_CMD2, quot >> 8);
@@ -1219,7 +1221,7 @@
 	serial_out(info, UART_ESI_CMD2, info->config.flow_on >> 8);
 	serial_out(info, UART_ESI_CMD2, info->config.flow_on);
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&esp_lock, flags);
 }
 
 static void rs_put_char(struct tty_struct *tty, unsigned char ch)
@@ -1233,7 +1235,7 @@
 	if (!tty || !info->xmit_buf)
 		return;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&esp_lock, flags);
 	if (info->xmit_cnt >= ESP_XMIT_SIZE - 1) {
 		restore_flags(flags);
 		return;
@@ -1242,7 +1244,7 @@
 	info->xmit_buf[info->xmit_head++] = ch;
 	info->xmit_head &= ESP_XMIT_SIZE-1;
 	info->xmit_cnt++;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&esp_lock, flags);
 }
 
 static void rs_flush_chars(struct tty_struct *tty)
@@ -1256,13 +1258,13 @@
 	if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf)
 		return;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&esp_lock, flags);
 	if (!(info->IER & UART_IER_THRI)) {
 		info->IER |= UART_IER_THRI;
 		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
 		serial_out(info, UART_ESI_CMD2, info->IER);
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&esp_lock, flags);
 }
 
 static int rs_write(struct tty_struct * tty,
@@ -1305,7 +1307,7 @@
 		ret += c;
 	}
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&esp_lock, flags);
 
 	if (info->xmit_cnt && !tty->stopped && !(info->IER & UART_IER_THRI)) {
 		info->IER |= UART_IER_THRI;
@@ -1313,7 +1315,7 @@
 		serial_out(info, UART_ESI_CMD2, info->IER);
 	}
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&esp_lock, flags);
 	return ret;
 }
 
@@ -1345,9 +1347,9 @@
 				
 	if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
 		return;
-	cli();
+	spin_lock_irq(&esp_lock);
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	sti();
+	spin_unlock_irq(&esp_lock);
 	tty_wakeup(tty);
 }
 
@@ -1372,13 +1374,13 @@
 	if (serial_paranoia_check(info, tty->name, "rs_throttle"))
 		return;
 	
-	cli();
+	spin_lock_irq(&esp_lock);
 	info->IER &= ~UART_IER_RDI;
 	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
 	serial_out(info, UART_ESI_CMD2, info->IER);
 	serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);
 	serial_out(info, UART_ESI_CMD2, 0x00);
-	sti();
+	spin_unlock_irq(&esp_lock);
 }
 
 static void rs_unthrottle(struct tty_struct * tty)
@@ -1394,13 +1396,13 @@
 	if (serial_paranoia_check(info, tty->name, "rs_unthrottle"))
 		return;
 	
-	cli();
+	spin_lock_irq(&esp_lock);
 	info->IER |= UART_IER_RDI;
 	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
 	serial_out(info, UART_ESI_CMD2, info->IER);
 	serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);
 	serial_out(info, UART_ESI_CMD2, info->config.rx_timeout);
-	sti();
+	spin_unlock_irq(&esp_lock);
 }
 
 /*
@@ -1654,13 +1656,13 @@
 
 		info->config.flow_off = new_config.flow_off;
 		info->config.flow_on = new_config.flow_on;
-		save_flags(flags); cli();
+		spin_lock_irqsave(&esp_lock, flags);
 		serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_LVL);
 		serial_out(info, UART_ESI_CMD2, new_config.flow_off >> 8);
 		serial_out(info, UART_ESI_CMD2, new_config.flow_off);
 		serial_out(info, UART_ESI_CMD2, new_config.flow_on >> 8);
 		serial_out(info, UART_ESI_CMD2, new_config.flow_on);
-		restore_flags(flags);
+		spin_unlock_irqrestore(&esp_lock, flags);
 	}
 
 	if ((new_config.rx_trigger != info->config.rx_trigger) ||
@@ -1669,7 +1671,7 @@
 
 		info->config.rx_trigger = new_config.rx_trigger;
 		info->config.tx_trigger = new_config.tx_trigger;
-		save_flags(flags); cli();
+		spin_lock_irqsave(&esp_lock, flags);
 		serial_out(info, UART_ESI_CMD1, ESI_SET_TRIGGER);
 		serial_out(info, UART_ESI_CMD2,
 			   new_config.rx_trigger >> 8);
@@ -1677,14 +1679,14 @@
 		serial_out(info, UART_ESI_CMD2,
 			   new_config.tx_trigger >> 8);
 		serial_out(info, UART_ESI_CMD2, new_config.tx_trigger);
-		restore_flags(flags);
+		spin_unlock_irqrestore(&esp_lock, flags);
 	}
 
 	if (new_config.rx_timeout != info->config.rx_timeout) {
 		unsigned long flags;
 
 		info->config.rx_timeout = new_config.rx_timeout;
-		save_flags(flags); cli();
+		spin_lock_irqsave(&esp_lock, flags);
 
 		if (info->IER & UART_IER_RDI) {
 			serial_out(info, UART_ESI_CMD1,
@@ -1693,7 +1695,7 @@
 				   new_config.rx_timeout);
 		}
 
-		restore_flags(flags);
+		spin_unlock_irqrestore(&esp_lock, flags);
 	}
 
 	if (!(info->flags & ASYNC_INITIALIZED))
@@ -1717,10 +1719,10 @@
 	unsigned char status;
 	unsigned int result;
 
-	cli();
+	spin_lock_irq(&esp_lock);
 	serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
 	status = serial_in(info, UART_ESI_STAT1);
-	sti();
+	spin_unlock_irq(&esp_lock);
 	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
 	return put_user(result,value);
 }
@@ -1737,10 +1739,10 @@
 		return -EIO;
 
 	control = info->MCR;
-	cli();
+	spin_lock_irq(&esp_lock);
 	serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
 	status = serial_in(info, UART_ESI_STAT2);
-	sti();
+	spin_unlock_irq(&esp_lock);
 	return    ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
 		| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
 		| ((status  & UART_MSR_DCD) ? TIOCM_CAR : 0)
@@ -1759,7 +1761,7 @@
 	if (tty->flags & (1 << TTY_IO_ERROR))
 		return -EIO;
 
-	cli();
+	spin_lock_irq(&esp_lock);
 
 	if (set & TIOCM_RTS)
 		info->MCR |= UART_MCR_RTS;
@@ -1774,7 +1776,7 @@
 	serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
 	serial_out(info, UART_ESI_CMD2, UART_MCR);
 	serial_out(info, UART_ESI_CMD2, info->MCR);
-	sti();
+	spin_unlock_irq(&esp_lock);
 	return 0;
 }
 
@@ -1789,7 +1791,7 @@
 	if (serial_paranoia_check(info, tty->name, "esp_break"))
 		return;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&esp_lock, flags);
 	if (break_state == -1) {
 		serial_out(info, UART_ESI_CMD1, ESI_ISSUE_BREAK);
 		serial_out(info, UART_ESI_CMD2, 0x01);
@@ -1799,7 +1801,7 @@
 		serial_out(info, UART_ESI_CMD1, ESI_ISSUE_BREAK);
 		serial_out(info, UART_ESI_CMD2, 0x00);
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&esp_lock, flags);
 }
 
 static int rs_ioctl(struct tty_struct *tty, struct file * file,
@@ -1849,17 +1851,17 @@
 		 * Caller should use TIOCGICOUNT to see which one it was
 		 */
 		 case TIOCMIWAIT:
-			cli();
+			spin_lock_irq(&esp_lock);
 			cprev = info->icount;	/* note the counters on entry */
-			sti();
+			spin_unlock_irq(&esp_lock);
 			while (1) {
 				interruptible_sleep_on(&info->delta_msr_wait);
 				/* see if a signal did it */
 				if (signal_pending(current))
 					return -ERESTARTSYS;
-				cli();
+				spin_lock_irq(&esp_lock);
 				cnow = info->icount;	/* atomic copy */
-				sti();
+				spin_unlock_irq(&esp_lock);
 				if (cnow.rng == cprev.rng &&
 				    cnow.dsr == cprev.dsr && 
 				    cnow.dcd == cprev.dcd &&
@@ -1886,9 +1888,9 @@
 		 *     RI where only 0->1 is counted.
 		 */
 		case TIOCGICOUNT:
-			cli();
+			spin_lock_irq(&esp_lock);
 			cnow = info->icount;
-			sti();
+			spin_unlock_irq(&esp_lock);
 			p_cuser = argp;
 			if (put_user(cnow.cts, &p_cuser->cts) ||
 			    put_user(cnow.dsr, &p_cuser->dsr) ||
@@ -1923,22 +1925,22 @@
 	if ((old_termios->c_cflag & CBAUD) &&
 		!(tty->termios->c_cflag & CBAUD)) {
 		info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
-		cli();
+		spin_lock_irq(&esp_lock);
 		serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
 		serial_out(info, UART_ESI_CMD2, UART_MCR);
 		serial_out(info, UART_ESI_CMD2, info->MCR);
-		sti();
+		spin_unlock_irq(&esp_lock);
 	}
 
 	/* Handle transition away from B0 status */
 	if (!(old_termios->c_cflag & CBAUD) &&
 		(tty->termios->c_cflag & CBAUD)) {
 		info->MCR |= (UART_MCR_DTR | UART_MCR_RTS);
-		cli();
+		spin_lock_irq(&esp_lock);
 		serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
 		serial_out(info, UART_ESI_CMD2, UART_MCR);
 		serial_out(info, UART_ESI_CMD2, info->MCR);
-		sti();
+		spin_unlock_irq(&esp_lock);
 	}
 
 	/* Handle turning of CRTSCTS */
@@ -1978,7 +1980,7 @@
 	if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
 		return;
 	
-	save_flags(flags); cli();
+	spin_lock_irqsave(&esp_lock, flags);
 	
 	if (tty_hung_up_p(filp)) {
 		DBG_CNT("before DEC-hung");
@@ -2058,7 +2060,7 @@
 	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
 	wake_up_interruptible(&info->close_wait);
 out:
-	restore_flags(flags);
+	spin_unlock_irqrestore(&esp_lock, flags);
 }
 
 static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
@@ -2076,7 +2078,7 @@
 	if (!char_time)
 		char_time = 1;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&esp_lock, flags);
 	serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
 	serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
 
@@ -2094,7 +2096,7 @@
 		serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
 	}
 	
-	restore_flags(flags);
+	spin_unlock_irqrestore(&esp_lock, flags);
 	set_current_state(TASK_RUNNING);
 }
 
@@ -2174,15 +2176,13 @@
 	printk("block_til_ready before block: ttys%d, count = %d\n",
 	       info->line, info->count);
 #endif
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&esp_lock, flags);
 	if (!tty_hung_up_p(filp)) 
 		info->count--;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&esp_lock, flags);
 	info->blocked_open++;
 	while (1) {
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&esp_lock, flags);
 		if ((tty->termios->c_cflag & CBAUD)) {
 			unsigned int scratch;
 
@@ -2194,7 +2194,7 @@
 			serial_out(info, UART_ESI_CMD2,
 				scratch | UART_MCR_DTR | UART_MCR_RTS);
 		}
-		restore_flags(flags);
+		spin_unlock_irqrestore(&esp_lock, flags);
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & ASYNC_INITIALIZED)) {
@@ -2335,7 +2335,7 @@
 	if (!request_region(info->port, REGION_SIZE, "esp serial"))
 		return -EIO;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&esp_lock, flags);
 	
 	/*
 	 * Check for ESP card
@@ -2372,7 +2372,7 @@
 	if (!port_detected)
 		release_region(info->port, REGION_SIZE);
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&esp_lock, flags);
 	return (port_detected);
 }
 
@@ -2569,12 +2569,11 @@
 	struct esp_pio_buffer *pio_buf;
 
 	/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&esp_lock, flags);
 	if ((e1 = tty_unregister_driver(esp_driver)))
 		printk("SERIAL: failed to unregister serial driver (%d)\n",
 		       e1);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&esp_lock, flags);
 	put_tty_driver(esp_driver);
 
 	while (ports) {
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 17:43:44.872008096 -0500
@@ -170,7 +170,7 @@
 
 config ESPSERIAL
 	tristate "Hayes ESP serial port support"
-	depends on SERIAL_NONSTANDARD && ISA && BROKEN_ON_SMP
+	depends on SERIAL_NONSTANDARD && ISA
 	help
 	  This is a driver which supports Hayes ESP serial ports.  Both single
 	  port cards and multiport cards are supported.  Make sure to read

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

* Re: [PATCH] esp: replace cli()/sti() with spin_lock_irqsave()/spin_unlock_irqrestore()
  2004-12-17 23:18 [PATCH] esp: replace cli()/sti() with spin_lock_irqsave()/spin_unlock_irqrestore() James Nelson
@ 2004-12-18  1:21 ` Jan Dittmer
  2004-12-18  3:46   ` Jim Nelson
  0 siblings, 1 reply; 3+ messages in thread
From: Jan Dittmer @ 2004-12-18  1:21 UTC (permalink / raw)
  To: James Nelson; +Cc: kernel-janitors, linux-kernel, akpm

James Nelson wrote:
> This is an attempt to make the esp driver SMP-correct.

You're trying to protect the info data, correct? Could you please
add a comment to the locks which data structures need to be
protected by them?!
Just blindly replacing cli/sti with spin_(un)lock doesn't make it
SMP save.

> diff -urN --exclude='*~' linux-2.6.10-rc3-mm1-original/drivers/char/esp.c linux-2.6.10-rc3-mm1/drivers/char/esp.c
> --- linux-2.6.10-rc3-mm1-original/drivers/char/esp.c	2004-12-03 16:52:13.000000000 -0500
> +++ linux-2.6.10-rc3-mm1/drivers/char/esp.c	2004-12-17 18:11:31.275037730 -0500
> @@ -212,14 +214,14 @@
>  	if (serial_paranoia_check(info, tty->name, "rs_stop"))
>  		return;
>  	
> -	save_flags(flags); cli();
> +	spin_lock_irqsave(&esp_lock, flags);

info can change between return and lock

>  	if (info->IER & UART_IER_THRI) {
>  		info->IER &= ~UART_IER_THRI;
>  		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
>  		serial_out(info, UART_ESI_CMD2, info->IER);
>  	}
>  
> -	restore_flags(flags);
> +	spin_unlock_irqrestore(&esp_lock, flags);
>  }
>  
>  static void rs_start(struct tty_struct *tty)
> @@ -230,13 +232,13 @@
>  	if (serial_paranoia_check(info, tty->name, "rs_start"))
>  		return;
>  	
> -	save_flags(flags); cli();
> +	spin_lock_irqsave(&esp_lock, flags);

same here.

>  	if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) {
>  		info->IER |= UART_IER_THRI;
>  		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
>  		serial_out(info, UART_ESI_CMD2, info->IER);
>  	}
> -	restore_flags(flags);
> +	spin_unlock_irqrestore(&esp_lock, flags);
>  }
>  
>  /*

Didn't read the rest. Are you sure you didn't introduce a deadlock in
the interrupt handler? {transmit,receiver}_chars_{pio,dma} also try to take
the lock.

Jan

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

* Re: [PATCH] esp: replace cli()/sti() with spin_lock_irqsave()/spin_unlock_irqrestore()
  2004-12-18  1:21 ` Jan Dittmer
@ 2004-12-18  3:46   ` Jim Nelson
  0 siblings, 0 replies; 3+ messages in thread
From: Jim Nelson @ 2004-12-18  3:46 UTC (permalink / raw)
  To: Jan Dittmer; +Cc: kernel-janitors, linux-kernel, akpm

Jan Dittmer wrote:
> James Nelson wrote:
> 
>>This is an attempt to make the esp driver SMP-correct.
> 
> 
> You're trying to protect the info data, correct? Could you please
> add a comment to the locks which data structures need to be
> protected by them?!
> Just blindly replacing cli/sti with spin_(un)lock doesn't make it
> SMP save.
> 

*sigh* Thought it wouldn't be that easy.



> 
>>diff -urN --exclude='*~' linux-2.6.10-rc3-mm1-original/drivers/char/esp.c linux-2.6.10-rc3-mm1/drivers/char/esp.c
>>--- linux-2.6.10-rc3-mm1-original/drivers/char/esp.c	2004-12-03 16:52:13.000000000 -0500
>>+++ linux-2.6.10-rc3-mm1/drivers/char/esp.c	2004-12-17 18:11:31.275037730 -0500
>>@@ -212,14 +214,14 @@
>> 	if (serial_paranoia_check(info, tty->name, "rs_stop"))
>> 		return;
>> 	
>>-	save_flags(flags); cli();
>>+	spin_lock_irqsave(&esp_lock, flags);
> 
> 
> info can change between return and lock
> 

Okay.  I see what you are talking about.  I'll dig into it tomorrow (after some 
sleep).

OTOH, this would have been SMP-incorrect even before cli()/sti() was dropped in 2.5 .

> 
>> 	if (info->IER & UART_IER_THRI) {
>> 		info->IER &= ~UART_IER_THRI;
>> 		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
>> 		serial_out(info, UART_ESI_CMD2, info->IER);
>> 	}
>> 
>>-	restore_flags(flags);
>>+	spin_unlock_irqrestore(&esp_lock, flags);
>> }
>> 
>> static void rs_start(struct tty_struct *tty)
>>@@ -230,13 +232,13 @@
>> 	if (serial_paranoia_check(info, tty->name, "rs_start"))
>> 		return;
>> 	
>>-	save_flags(flags); cli();
>>+	spin_lock_irqsave(&esp_lock, flags);
> 
> 
> same here.
> 
> 
>> 	if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) {
>> 		info->IER |= UART_IER_THRI;
>> 		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
>> 		serial_out(info, UART_ESI_CMD2, info->IER);
>> 	}
>>-	restore_flags(flags);
>>+	spin_unlock_irqrestore(&esp_lock, flags);
>> }
>> 
>> /*
> 
> 
> Didn't read the rest. Are you sure you didn't introduce a deadlock in
> the interrupt handler? {transmit,receiver}_chars_{pio,dma} also try to take
> the lock.
> 

Hm.  I made the assumption (silly me) that the code was inherently SMP-correct, 
and just needed the function calls replaced.

Live and learn.

Jim

> Jan
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 


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

end of thread, other threads:[~2004-12-18  3:46 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-12-17 23:18 [PATCH] esp: replace cli()/sti() with spin_lock_irqsave()/spin_unlock_irqrestore() James Nelson
2004-12-18  1:21 ` Jan Dittmer
2004-12-18  3:46   ` Jim Nelson

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