Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 315300 Details for
Bug 445211
[RFE] DTR/DSR flow control
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
[2/2] add support for DTR/DSR flow control
dtrdsr.patch (text/plain), 9.33 KB, created by
Aristeu Rozanski
on 2008-08-28 21:17:49 UTC
(
hide
)
Description:
[2/2] add support for DTR/DSR flow control
Filename:
MIME Type:
Creator:
Aristeu Rozanski
Created:
2008-08-28 21:17:49 UTC
Size:
9.33 KB
patch
obsolete
>https://bugzilla.redhat.com/show_bug.cgi?id=445215 > >8250: add support for DTR/DSR hardware flow control > >This patch adds support for DTR/DSR hardware flow control to 8250 >driver. The upstream version will differ from this one, since it'll >take a bigger rework. > >Tested with success by the customer and by me on a serial P.O.S. printer. > >--- > drivers/serial/8250.c | 16 ++++++- > drivers/serial/serial_core.c | 98 ++++++++++++++++++++++++++++++++++++++++++- > include/linux/serial_core.h | 50 ++++++++++++++------- > 3 files changed, 143 insertions(+), 21 deletions(-) > >--- tree.orig/drivers/serial/8250.c 2008-08-28 13:34:55.000000000 -0400 >+++ tree/drivers/serial/8250.c 2008-08-28 13:45:50.000000000 -0400 >@@ -1310,7 +1310,7 @@ static unsigned int check_modem_status(s > if (status & UART_MSR_TERI) > up->port.icount.rng++; > if (status & UART_MSR_DDSR) >- up->port.icount.dsr++; >+ uart_handle_dsr_change(&up->port, status & UART_MSR_DSR); > if (status & UART_MSR_DDCD) > uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); > if (status & UART_MSR_DCTS) >@@ -1619,8 +1619,20 @@ static inline void wait_for_xmitr(struct > > /* Wait up to 1s for flow control if necessary */ > if (up->port.flags & UPF_CONS_FLOW) { >+ struct uart_info *info = up->port.info; >+ unsigned int msr; >+ > tmout = 1000000; >- while (!(serial_in(up, UART_MSR) & UART_MSR_CTS) && --tmout) { >+ while (--tmout) { >+ msr = serial_in(up, UART_MSR); >+ >+ if ((info->flags & UIF_CTS_FLOW) && >+ (msr & UART_MSR_CTS)) >+ break; >+ else if ((info->flags & UIF_DSR_FLOW) && >+ (msr & UART_MSR_DSR)) >+ break; >+ > udelay(1); > touch_nmi_watchdog(); > } >--- tree.orig/drivers/serial/serial_core.c 2008-08-28 13:34:55.000000000 -0400 >+++ tree/drivers/serial/serial_core.c 2008-08-28 13:45:50.000000000 -0400 >@@ -199,6 +199,13 @@ static int uart_startup(struct uart_stat > spin_unlock_irq(&port->lock); > } > >+ if (info->flags & UIF_DSR_FLOW) { >+ spin_lock_irq(&port->lock); >+ if (!(port->ops->get_mctrl(port) & TIOCM_DSR)) >+ info->tty->hw_stopped = 1; >+ spin_unlock_irq(&port->lock); >+ } >+ > info->flags |= UIF_INITIALIZED; > > clear_bit(TTY_IO_ERROR, &info->tty->flags); >@@ -591,6 +598,8 @@ static void uart_throttle(struct tty_str > > if (tty->termios->c_cflag & CRTSCTS) > uart_clear_mctrl(state->port, TIOCM_RTS); >+ if (state->info->flags & UIF_DSR_FLOW) >+ uart_clear_mctrl(state->port, TIOCM_DTR); > } > > static void uart_unthrottle(struct tty_struct *tty) >@@ -607,6 +616,8 @@ static void uart_unthrottle(struct tty_s > > if (tty->termios->c_cflag & CRTSCTS) > uart_set_mctrl(port, TIOCM_RTS); >+ if (state->info->flags & UIF_DSR_FLOW) >+ uart_set_mctrl(port, TIOCM_DTR); > } > > static int uart_get_info(struct uart_state *state, >@@ -1168,7 +1179,10 @@ static void uart_set_termios(struct tty_ > if (!(cflag & CRTSCTS) || > !test_bit(TTY_THROTTLED, &tty->flags)) > mask |= TIOCM_RTS; >- uart_set_mctrl(state->port, mask); >+ if (state->info->flags & UIF_DSR_FLOW) >+ mask &= ~TIOCM_DTR; >+ if (mask) >+ uart_set_mctrl(state->port, mask); > } > > /* Handle turning off CRTSCTS */ >@@ -1182,6 +1196,7 @@ static void uart_set_termios(struct tty_ > /* Handle turning on CRTSCTS */ > if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { > spin_lock_irqsave(&state->port->lock, flags); >+ state->port->info->flags &= ~UIF_DSR_FLOW; > if (!(state->port->ops->get_mctrl(state->port) & TIOCM_CTS)) { > tty->hw_stopped = 1; > state->port->ops->stop_tx(state->port); >@@ -1202,6 +1217,81 @@ static void uart_set_termios(struct tty_ > #endif > } > >+static void uart_set_termiox(struct tty_struct *tty, struct termiox *tnew) >+{ >+ struct uart_state *state = tty->driver_data; >+ long flags; >+ >+ if ((tnew->x_cflag & (CTSXON | RTSXOFF)) == (CTSXON | RTSXOFF)) { >+ /* Handle turning on CRTSCTS */ >+ spin_lock_irqsave(&state->port->lock, flags); >+ tty->termios->c_cflag |= CRTSCTS; >+ state->port->info->flags &= ~UIF_DSR_FLOW; >+ state->port->info->flags |= UIF_CTS_FLOW; >+ >+ if (!(state->port->ops->get_mctrl(state->port) & TIOCM_CTS)) { >+ tty->hw_stopped = 1; >+ state->port->ops->stop_tx(state->port); >+ } else if (tty->hw_stopped) { >+ tty->hw_stopped = 0; >+ __uart_start(tty); >+ } >+ spin_unlock_irqrestore(&state->port->lock, flags); >+ >+ uart_clear_mctrl(state->port, TIOCM_RTS | TIOCM_DTR); >+ >+ if (tty->termios->c_cflag & CBAUD) { >+ unsigned int mask = TIOCM_DTR; >+ >+ if (!test_bit(TTY_THROTTLED, &tty->flags)) >+ mask |= TIOCM_RTS; >+ uart_set_mctrl(state->port, mask); >+ } >+ } else if ((tnew->x_cflag & (DSRXON | DTRXOFF)) == (DSRXON | DTRXOFF)) { >+ spin_lock_irqsave(&state->port->lock, flags); >+ tty->termios->c_cflag &= ~CRTSCTS; >+ state->port->info->flags &= ~UIF_CTS_FLOW; >+ state->port->info->flags |= UIF_DSR_FLOW; >+ >+ if (!(state->port->ops->get_mctrl(state->port) & TIOCM_DSR)) { >+ tty->hw_stopped = 1; >+ state->port->ops->stop_tx(state->port); >+ } else if (tty->hw_stopped) { >+ tty->hw_stopped = 0; >+ __uart_start(tty); >+ } >+ spin_unlock_irqrestore(&state->port->lock, flags); >+ >+ uart_clear_mctrl(state->port, TIOCM_RTS | TIOCM_DTR); >+ >+ if (tty->termios->c_cflag & CBAUD) >+ uart_set_mctrl(state->port, TIOCM_DTR); >+ } else if (!(tnew->x_cflag & (CTSXON | RTSXOFF | DSRXON | DTRXOFF))) { >+ /* disabling flow control */ >+ spin_lock_irqsave(&state->port->lock, flags); >+ tty->termios->c_cflag &= ~CRTSCTS; >+ state->port->info->flags &= ~UIF_CTS_FLOW; >+ state->port->info->flags &= ~UIF_DSR_FLOW; >+ >+ tty->hw_stopped = 0; >+ __uart_start(tty); >+ spin_unlock_irqrestore(&state->port->lock, flags); >+ >+ uart_clear_mctrl(state->port, TIOCM_RTS); >+ uart_set_mctrl(state->port, TIOCM_DTR); >+ } >+} >+ >+static void uart_get_termiox(struct tty_struct *tty, struct termiox *t) >+{ >+ struct uart_state *state = tty->driver_data; >+ >+ if (state->info->flags & UIF_CTS_FLOW) >+ t->x_cflag = CTSXON | RTSXOFF; >+ else if (state->info->flags & UIF_DSR_FLOW) >+ t->x_cflag = DSRXON | DTRXOFF; >+} >+ > /* > * In 2.4.5, calls to this will be serialized via the BKL in > * linux/drivers/char/tty_io.c:tty_release() >@@ -1468,7 +1558,8 @@ uart_block_til_ready(struct file *filp, > * not set RTS here - we want to make sure we catch > * the data from the modem. > */ >- if (info->tty->termios->c_cflag & CBAUD) >+ if (info->tty->termios->c_cflag & CBAUD && >+ !(info->flags & UIF_DSR_FLOW)) > uart_set_mctrl(port, TIOCM_DTR); > > /* >@@ -2183,6 +2274,7 @@ int uart_register_driver(struct uart_dri > normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; > normal->driver_state = drv; > tty_set_operations(normal, &uart_ops); >+ tty_register_termiox_handler(normal, uart_get_termiox, uart_set_termiox); > > /* > * Initialise the UART state(s). >@@ -2217,7 +2309,9 @@ int uart_register_driver(struct uart_dri > void uart_unregister_driver(struct uart_driver *drv) > { > struct tty_driver *p = drv->tty_driver; >+ > tty_unregister_driver(p); >+ tty_unregister_termiox_handler(p); > put_tty_driver(p); > kfree(drv->state); > drv->tty_driver = NULL; >--- tree.orig/include/linux/serial_core.h 2008-08-28 13:34:55.000000000 -0400 >+++ tree/include/linux/serial_core.h 2008-08-28 13:45:50.000000000 -0400 >@@ -315,6 +315,7 @@ struct uart_info { > * Definitions for info->flags. These are _private_ to serial_core, and > * are specific to this structure. They may be queried by low level drivers. > */ >+#define UIF_DSR_FLOW ((__force uif_t) (1 << 24)) > #define UIF_CHECK_CD ((__force uif_t) (1 << 25)) > #define UIF_CTS_FLOW ((__force uif_t) (1 << 26)) > #define UIF_NORMAL_ACTIVE ((__force uif_t) (1 << 29)) >@@ -474,34 +475,48 @@ uart_handle_dcd_change(struct uart_port > } > > /** >- * uart_handle_cts_change - handle a change of clear-to-send state >+ * uart_handle_flow_control_change - handle a change of CTS or DSR > * @port: uart_port structure for the open port >- * @status: new clear to send status, nonzero if active >+ * @status: new CTS/DTR status, nonzero if active > */ > static inline void >-uart_handle_cts_change(struct uart_port *port, unsigned int status) >+uart_handle_flow_control_change(struct uart_port *port, unsigned int status) > { > struct uart_info *info = port->info; > struct tty_struct *tty = info->tty; > >- port->icount.cts++; >- >- if (info->flags & UIF_CTS_FLOW) { >- if (tty->hw_stopped) { >- if (status) { >- tty->hw_stopped = 0; >- port->ops->start_tx(port); >- uart_write_wakeup(port); >- } >- } else { >- if (!status) { >- tty->hw_stopped = 1; >- port->ops->stop_tx(port); >- } >+ if (tty->hw_stopped) { >+ if (status) { >+ tty->hw_stopped = 0; >+ port->ops->start_tx(port); >+ uart_write_wakeup(port); >+ } >+ } else { >+ if (!status) { >+ tty->hw_stopped = 1; >+ port->ops->stop_tx(port); > } > } > } > >+static inline void >+uart_handle_cts_change(struct uart_port *port, unsigned int status) >+{ >+ struct uart_info *info = port->info; >+ port->icount.cts++; >+ if (info->flags & UIF_CTS_FLOW) >+ uart_handle_flow_control_change(port, status); >+} >+ >+static inline void >+uart_handle_dsr_change(struct uart_port *port, unsigned int status) >+{ >+ struct uart_info *info = port->info; >+ port->icount.dsr++; >+ if (info->flags & UIF_DSR_FLOW) >+ uart_handle_flow_control_change(port, status); >+} >+ > #include <linux/tty_flip.h> > > static inline void >@@ -526,6 +541,7 @@ uart_insert_char(struct uart_port *port, > */ > #define UART_ENABLE_MS(port,cflag) ((port)->flags & UPF_HARDPPS_CD || \ > (cflag) & CRTSCTS || \ >+ ((port)->info && ((port)->info->flags & UIF_DSR_FLOW)) || \ > !((cflag) & CLOCAL)) > > #endif
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 445211
:
308359
|
308360
|
309219
|
309849
|
315299
| 315300 |
315301