From: David Woodhouse <dwmw2@infradead.org>
To: Andrew Morton <akpm@osdl.org>
Cc: rmk@arm.linux.org.uk, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] Correctly flush 8250 buffers, notify ldisc of line status changes.
Date: Tue, 09 Nov 2004 11:07:17 +0000 [thread overview]
Message-ID: <1099998437.6081.68.camel@localhost.localdomain> (raw)
In-Reply-To: <20041109012212.463009c7.akpm@osdl.org>
On Tue, 2004-11-09 at 01:22 -0800, Andrew Morton wrote:
> David Woodhouse <dwmw2@infradead.org> 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().
>
> Your patch makes my computer stop working, which saddens me.
> Maybe the lock which uart_flush_buffer() takes is the same as the lock
> which serial8250_flush_buffer() takes?
Er, yes it is, sorry. This version should make you less unhappy:
===== drivers/char/tty_io.c 1.152 vs edited =====
--- 1.152/drivers/char/tty_io.c Mon Oct 25 21:06:49 2004
+++ edited/drivers/char/tty_io.c Fri Nov 5 13:03:32 2004
@@ -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.77 vs edited =====
--- 1.77/drivers/serial/8250.c Mon Oct 25 13:05:26 2004
+++ edited/drivers/serial/8250.c Tue Nov 9 11:05:15 2004
@@ -356,6 +356,20 @@
}
}
+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;
+
+ fcr = serial_inp(up, UART_FCR);
+ fcr |= UART_FCR_CLEAR_XMIT;
+ serial_outp(up, UART_FCR, fcr);
+}
+
/*
* IER sleep support. UARTs which have EFRs need the "extended
* capability" bit enabled. Note that on XR16C850s, we need to
@@ -1120,7 +1134,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);
}
/*
@@ -1940,6 +1954,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 Wed Apr 14 17:31:16 2004
+++ edited/drivers/serial/amba-pl010.c Fri Nov 5 13:03:32 2004
@@ -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.4 vs edited =====
--- 1.4/drivers/serial/amba-pl011.c Tue Oct 5 11:04:12 2004
+++ edited/drivers/serial/amba-pl011.c Fri Nov 5 13:03:32 2004
@@ -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.3 vs edited =====
--- 1.3/drivers/serial/au1x00_uart.c Sat Oct 23 00:06:15 2004
+++ edited/drivers/serial/au1x00_uart.c Fri Nov 5 13:03:32 2004
@@ -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.2 vs edited =====
--- 1.2/drivers/serial/icom.c Wed Oct 20 09:37:15 2004
+++ edited/drivers/serial/icom.c Fri Nov 5 13:03:32 2004
@@ -692,8 +692,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 Thu Feb 19 03:42:44 2004
+++ edited/drivers/serial/ip22zilog.c Fri Nov 5 13:03:32 2004
@@ -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.15 vs edited =====
--- 1.15/drivers/serial/pmac_zilog.c Wed Oct 20 09:37:15 2004
+++ edited/drivers/serial/pmac_zilog.c Fri Nov 5 13:03:32 2004
@@ -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 Tue Sep 28 20:35:56 2004
+++ edited/drivers/serial/pxa.c Fri Nov 5 13:03:32 2004
@@ -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 Fri Apr 9 22:55:47 2004
+++ edited/drivers/serial/sa1100.c Fri Nov 5 13:03:32 2004
@@ -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.92 vs edited =====
--- 1.92/drivers/serial/serial_core.c Thu Oct 21 18:03:22 2004
+++ edited/drivers/serial/serial_core.c Fri Nov 5 13:03:32 2004
@@ -567,6 +567,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 Sat Jun 5 11:30:48 2004
+++ edited/drivers/serial/serial_lh7a40x.c Fri Nov 5 13:03:32 2004
@@ -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 Thu Aug 26 23:38:22 2004
+++ edited/drivers/serial/sunsab.c Fri Nov 5 13:03:32 2004
@@ -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.45 vs edited =====
--- 1.45/drivers/serial/sunsu.c Mon Sep 20 21:46:03 2004
+++ edited/drivers/serial/sunsu.c Fri Nov 5 13:03:32 2004
@@ -453,7 +453,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 Mon Sep 20 21:46:03 2004
+++ edited/drivers/serial/sunzilog.c Fri Nov 5 13:03:32 2004
@@ -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 Thu Apr 29 13:14:52 2004
+++ edited/drivers/serial/uart00.c Fri Nov 5 13:03:32 2004
@@ -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.43 vs edited =====
--- 1.43/include/linux/serial_core.h Tue Sep 14 01:23:24 2004
+++ edited/include/linux/serial_core.h Fri Nov 5 13:03:32 2004
@@ -108,6 +108,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 Thu Oct 21 18:03:22 2004
+++ edited/include/linux/tty.h Fri Nov 5 13:03:32 2004
@@ -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 Thu Oct 21 18:03:22 2004
+++ edited/include/linux/tty_ldisc.h Fri Nov 5 13:03:32 2004
@@ -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
next prev parent reply other threads:[~2004-11-09 11:26 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
2004-11-09 9:22 ` Andrew Morton
2004-11-09 11:07 ` David Woodhouse [this message]
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=1099998437.6081.68.camel@localhost.localdomain \
--to=dwmw2@infradead.org \
--cc=akpm@osdl.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.