All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Woodhouse <dwmw2@infradead.org>
To: rmk@arm.linux.org.uk
Cc: linux-kernel@vger.kernel.org
Subject: Re: [PATCH] Correctly flush 8250 buffers, notify ldisc of line status changes.
Date: Fri, 05 Nov 2004 13:08:51 +0000	[thread overview]
Message-ID: <1099660132.20469.74.camel@localhost.localdomain> (raw)
In-Reply-To: <1099659997.20469.71.camel@localhost.localdomain>

On Fri, 2004-11-05 at 13:06 +0000, David Woodhouse wrote:
> We weren't flushing the TX FIFO on 8250 uarts when uart_flush_buffer()
> was called. This adds a flush_buffer() method to the uart_port
> operations and calls it from uart_flush_buffer().
> 
> This also adds a method to the line discipline which is called upon line
> status changes, and uses the helper function for that to clean up the
> uart hardware drivers slightly, removing the explicit wakeup on
> delta_msr_wait which is used for TIOCMIWAIT.
> 
> I'll be putting together a line discipline which actually needs this
> callback shortly.

Doh.

===== drivers/char/tty_io.c 1.152 vs edited =====
--- 1.152/drivers/char/tty_io.c	2004-10-25 21:06:49 +01:00
+++ edited/drivers/char/tty_io.c	2004-11-05 12:28:24 +00:00
@@ -720,6 +720,26 @@
 EXPORT_SYMBOL_GPL(tty_wakeup);
 
 /**
+ *	tty_status_change -	notify of line status changes
+ *	@tty: terminal
+ *
+ *	Helper for informing the line discipline that the modem
+ *	status lines may have changed.
+ */
+
+void tty_status_changed(struct tty_struct *tty)
+{
+	struct tty_ldisc *ld = tty_ldisc_ref(tty);
+	if(ld) {
+		if(ld->status_changed)
+			ld->status_changed(tty);
+		tty_ldisc_deref(ld);
+	}
+}
+
+EXPORT_SYMBOL_GPL(tty_status_changed);
+
+/**
  *	tty_ldisc_flush	-	flush line discipline queue
  *	@tty: tty
  *
===== drivers/serial/8250.c 1.89 vs edited =====
--- 1.89/drivers/serial/8250.c	2004-11-02 09:31:48 +00:00
+++ edited/drivers/serial/8250.c	2004-11-05 12:59:51 +00:00
@@ -351,6 +351,24 @@
 	}
 }
 
+static void serial8250_flush_buffer(struct uart_port *port)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	unsigned long flags;
+	unsigned char fcr;
+
+	if (!up->capabilities & UART_CAP_FIFO)
+		return;
+
+	spin_lock_irqsave(&up->port.lock, flags);
+
+	fcr = serial_inp(up, UART_FCR);
+	fcr |= UART_FCR_CLEAR_XMIT;
+	serial_outp(up, UART_FCR, fcr);
+
+	spin_unlock_irqrestore(&up->port.lock, flags);
+}
+	
 /*
  * IER sleep support.  UARTs which have EFRs need the "extended
  * capability" bit enabled.  Note that on XR16C850s, we need to
@@ -1115,7 +1133,7 @@
 	if (status & UART_MSR_DCTS)
 		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
 
-	wake_up_interruptible(&up->port.info->delta_msr_wait);
+	uart_status_changed(&up->port);
 }
 
 /*
@@ -1916,6 +1934,7 @@
 
 static struct uart_ops serial8250_pops = {
 	.tx_empty	= serial8250_tx_empty,
+	.flush_buffer	= serial8250_flush_buffer,
 	.set_mctrl	= serial8250_set_mctrl,
 	.get_mctrl	= serial8250_get_mctrl,
 	.stop_tx	= serial8250_stop_tx,
===== drivers/serial/amba-pl010.c 1.23 vs edited =====
--- 1.23/drivers/serial/amba-pl010.c	2004-04-14 17:31:16 +01:00
+++ edited/drivers/serial/amba-pl010.c	2004-11-05 12:51:09 +00:00
@@ -277,7 +277,7 @@
 	if (delta & UART01x_FR_CTS)
 		uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
 
-	wake_up_interruptible(&uap->port.info->delta_msr_wait);
+	uart_status_changed(&uap->port);
 }
 
 static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs)
===== drivers/serial/amba-pl011.c 1.5 vs edited =====
--- 1.5/drivers/serial/amba-pl011.c	2004-10-30 15:09:16 +01:00
+++ edited/drivers/serial/amba-pl011.c	2004-11-05 12:51:31 +00:00
@@ -240,7 +240,7 @@
 	if (delta & UART01x_FR_CTS)
 		uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
 
-	wake_up_interruptible(&uap->port.info->delta_msr_wait);
+	uart_status_changed(&uap->port);
 }
 
 static irqreturn_t pl011_int(int irq, void *dev_id, struct pt_regs *regs)
===== drivers/serial/au1x00_uart.c 1.4 vs edited =====
--- 1.4/drivers/serial/au1x00_uart.c	2004-10-30 23:12:12 +01:00
+++ edited/drivers/serial/au1x00_uart.c	2004-11-05 12:51:57 +00:00
@@ -375,7 +375,7 @@
 	if (status & UART_MSR_DCTS)
 		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
 
-	wake_up_interruptible(&up->port.info->delta_msr_wait);
+	uart_status_changed(&up->port);
 }
 
 /*
===== drivers/serial/icom.c 1.3 vs edited =====
--- 1.3/drivers/serial/icom.c	2004-11-01 12:29:39 +00:00
+++ edited/drivers/serial/icom.c	2004-11-05 12:52:33 +00:00
@@ -686,8 +686,8 @@
 			uart_handle_cts_change(&icom_port->uart_port,
 					       delta_status & ICOM_CTS);
 
-		wake_up_interruptible(&icom_port->uart_port.info->
-				      delta_msr_wait);
+		uart_status_changed(&icom_port->uart_port);
+
 		old_status = status;
 	}
 	spin_unlock(&icom_port->uart_port.lock);
===== drivers/serial/ip22zilog.c 1.1 vs edited =====
--- 1.1/drivers/serial/ip22zilog.c	2004-02-19 03:42:44 +00:00
+++ edited/drivers/serial/ip22zilog.c	2004-11-05 12:53:18 +00:00
@@ -383,7 +383,7 @@
 			uart_handle_cts_change(&up->port,
 					       (status & CTS));
 
-		wake_up_interruptible(&up->port.info->delta_msr_wait);
+		uart_status_changed(&up->port.info);
 	}
 
 	up->prev_status = status;
===== drivers/serial/pmac_zilog.c 1.16 vs edited =====
--- 1.16/drivers/serial/pmac_zilog.c	2004-11-01 12:29:40 +00:00
+++ edited/drivers/serial/pmac_zilog.c	2004-11-05 12:53:45 +00:00
@@ -361,7 +361,7 @@
 			uart_handle_cts_change(&uap->port,
 					       !(status & CTS));
 
-		wake_up_interruptible(&uap->port.info->delta_msr_wait);
+		uart_status_changed(&uap->port.info);
 	}
 
 	uap->prev_status = status;
===== drivers/serial/pxa.c 1.5 vs edited =====
--- 1.5/drivers/serial/pxa.c	2004-09-28 20:35:56 +01:00
+++ edited/drivers/serial/pxa.c	2004-11-05 12:54:06 +00:00
@@ -251,7 +251,7 @@
 	if (status & UART_MSR_DCTS)
 		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
 
-	wake_up_interruptible(&up->port.info->delta_msr_wait);
+	uart_status_changed(&up->port.info);
 }
 
 /*
===== drivers/serial/sa1100.c 1.26 vs edited =====
--- 1.26/drivers/serial/sa1100.c	2004-04-09 22:55:47 +01:00
+++ edited/drivers/serial/sa1100.c	2004-11-05 12:54:32 +00:00
@@ -120,7 +120,7 @@
 	if (changed & TIOCM_CTS)
 		uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
 
-	wake_up_interruptible(&sport->port.info->delta_msr_wait);
+	uart_status_changed(&sport->port);
 }
 
 /*
===== drivers/serial/serial_core.c 1.94 vs edited =====
--- 1.94/drivers/serial/serial_core.c	2004-11-01 12:29:41 +00:00
+++ edited/drivers/serial/serial_core.c	2004-11-05 12:35:05 +00:00
@@ -515,6 +515,8 @@
 
 	spin_lock_irqsave(&port->lock, flags);
 	uart_circ_clear(&state->info->xmit);
+	if (port->ops->flush_buffer)
+		port->ops->flush_buffer(port);
 	spin_unlock_irqrestore(&port->lock, flags);
 	tty_wakeup(tty);
 }
===== drivers/serial/serial_lh7a40x.c 1.1 vs edited =====
--- 1.1/drivers/serial/serial_lh7a40x.c	2004-06-05 11:30:48 +01:00
+++ edited/drivers/serial/serial_lh7a40x.c	2004-11-05 12:54:55 +00:00
@@ -263,7 +263,7 @@
 	if (delta & CTS)
 		uart_handle_cts_change (port, status & CTS);
 
-	wake_up_interruptible (&port->info->delta_msr_wait);
+	uart_status_changed(port);
 }
 
 static irqreturn_t lh7a40xuart_int (int irq, void* dev_id,
===== drivers/serial/sunsab.c 1.35 vs edited =====
--- 1.35/drivers/serial/sunsab.c	2004-08-26 23:38:22 +01:00
+++ edited/drivers/serial/sunsab.c	2004-11-05 12:55:15 +00:00
@@ -305,7 +305,7 @@
 		up->port.icount.dsr++;
 	}
 
-	wake_up_interruptible(&up->port.info->delta_msr_wait);
+	uart_status_changed(&up->port.info);
 }
 
 static irqreturn_t sunsab_interrupt(int irq, void *dev_id, struct pt_regs *regs)
===== drivers/serial/sunsu.c 1.46 vs edited =====
--- 1.46/drivers/serial/sunsu.c	2004-10-31 21:33:17 +00:00
+++ edited/drivers/serial/sunsu.c	2004-11-05 12:55:29 +00:00
@@ -452,7 +452,7 @@
 	if (status & UART_MSR_DCTS)
 		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
 
-	wake_up_interruptible(&up->port.info->delta_msr_wait);
+	uart_status_changed(&up->port.info);
 }
 
 static irqreturn_t sunsu_serial_interrupt(int irq, void *dev_id, struct pt_regs *regs)
===== drivers/serial/sunzilog.c 1.46 vs edited =====
--- 1.46/drivers/serial/sunzilog.c	2004-09-20 21:46:03 +01:00
+++ edited/drivers/serial/sunzilog.c	2004-11-05 12:55:46 +00:00
@@ -464,7 +464,7 @@
 			uart_handle_cts_change(&up->port,
 					       (status & CTS));
 
-		wake_up_interruptible(&up->port.info->delta_msr_wait);
+		uart_status_changed(&up->port.info);
 	}
 
 	up->prev_status = status;
===== drivers/serial/uart00.c 1.17 vs edited =====
--- 1.17/drivers/serial/uart00.c	2004-04-29 13:14:52 +01:00
+++ edited/drivers/serial/uart00.c	2004-11-05 12:56:06 +00:00
@@ -249,7 +249,7 @@
 	if (status & UART_MSR_DCTS_MSK)
 		uart_handle_cts_change(port, status & UART_MSR_CTS_MSK);
 
-	wake_up_interruptible(&port->info->delta_msr_wait);
+	uart_status_changed(port);
 }
 
 static irqreturn_t uart00_int(int irq, void *dev_id, struct pt_regs *regs)
===== include/linux/serial_core.h 1.45 vs edited =====
--- 1.45/include/linux/serial_core.h	2004-10-30 21:24:41 +01:00
+++ edited/include/linux/serial_core.h	2004-11-05 13:00:36 +00:00
@@ -111,6 +111,7 @@
  */
 struct uart_ops {
 	unsigned int	(*tx_empty)(struct uart_port *);
+	void		(*flush_buffer)(struct uart_port *);
 	void		(*set_mctrl)(struct uart_port *, unsigned int mctrl);
 	unsigned int	(*get_mctrl)(struct uart_port *);
 	void		(*stop_tx)(struct uart_port *, unsigned int tty_stop);
@@ -448,6 +449,16 @@
 			}
 		}
 	}
+}
+
+/**
+ *	uart_status_changed - notify ldisc of a change of modem status lines
+ *	@post: uart_port structure for the open port
+ */
+static inline void uart_status_changed(struct uart_port *port)
+{
+	tty_status_changed(port->info->tty);
+	wake_up_interruptible(&port->info->delta_msr_wait);
 }
 
 /*
===== include/linux/tty.h 1.30 vs edited =====
--- 1.30/include/linux/tty.h	2004-10-21 18:03:22 +01:00
+++ edited/include/linux/tty.h	2004-11-05 12:38:02 +00:00
@@ -374,6 +374,7 @@
 extern void tty_ldisc_put(int);
 
 extern void tty_wakeup(struct tty_struct *tty);
+extern void tty_status_changed(struct tty_struct *tty);
 extern void tty_ldisc_flush(struct tty_struct *tty);
 
 struct semaphore;
===== include/linux/tty_ldisc.h 1.7 vs edited =====
--- 1.7/include/linux/tty_ldisc.h	2004-10-21 18:03:22 +01:00
+++ edited/include/linux/tty_ldisc.h	2004-11-05 12:08:29 +00:00
@@ -102,6 +102,11 @@
  *	cease I/O to the tty driver. Can sleep. The driver should
  *	seek to perform this action quickly but should wait until
  *	any pending driver I/O is completed.
+ *
+ * void (*status_changed)(struct tty_struct *)
+ *
+ *	Called when the modem status lines (CTS, DSR, DCD etc.) are
+ *	changed. May not sleep. 
  */
 
 #include <linux/fs.h>
@@ -138,6 +143,7 @@
 			       char *fp, int count);
 	int	(*receive_room)(struct tty_struct *);
 	void	(*write_wakeup)(struct tty_struct *);
+	void	(*status_changed)(struct tty_struct *);
 
 	struct  module *owner;
 	

-- 
dwmw2


  reply	other threads:[~2004-11-05 13:18 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-11-05 13:06 [PATCH] Correctly flush 8250 buffers, notify ldisc of line status changes David Woodhouse
2004-11-05 13:08 ` David Woodhouse [this message]
2004-11-09  9:22 ` Andrew Morton
2004-11-09 11:07   ` David Woodhouse
2004-11-09 11:15     ` Alan Cox
2004-11-09 13:28       ` Russell King
2004-11-09 13:17         ` Alan Cox
2004-11-09 14:39           ` David Woodhouse
2004-11-09 13:49             ` Alan Cox
2004-11-09 14:47           ` Russell King
2004-11-09 14:47             ` Alan Cox
2004-11-13 18:10               ` Russell King
2004-11-13 20:52                 ` Alan Cox
2004-11-13 22:40                   ` Nicolas Pitre
2004-11-09 14:39       ` David Woodhouse

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1099660132.20469.74.camel@localhost.localdomain \
    --to=dwmw2@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rmk@arm.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.