Handling of automatic flow control in UART drivers
Hi,
We have problem with automatic flow control (i.e. auto RTS/CTS handshaking) in our uart driver (men_z135_uart.c). It's probably less a technical but a problem with me understanding the API.
I active the hardware auto flow control feature on the CRTSCTS flag in my uart_ops->set_termios() function. But then the RTS flag is set on every call of the uart_ops->set_mctrl() function, this seems to confuse the hardware. Is there a way to tell the tty layer that flow control is handled solely by hardware? I.e. is there a way of telling serial core to leave out the calls to uart_set_mctrl()/uart_clear_mctrl() in uart_throttle()/uart_unthrottle(), or is setting UPF_FLOW_HARD and then implementing a dummy port->ops->{un}throttle() the correct way?
Are there any drivers that use a hardware's automatic flow control feature I can use as an example? A fast grep on AFE reveals some spots, but I can't really find a difference to my implementation.
Thanks in advance,
Johannes
Quoted 4 lines · Johannes Thumshirn
I active the hardware auto flow control feature on the CRTSCTS flag in my
uart_ops->set_termios()function. But then the RTS flag is set on every call of theuart_ops->set_mctrl()function, this seems to confuse the hardware.
Perhaps in that situation you should ignore the RTS setting in set_mctrl() if CRTSCTS is enabled.
Signature · 3 lines
Grant Edwards grant.b.edwards Yow! Zippy's brain cells
at are straining to bridge
gmail.com synapses ...Quoted 15 lines · Johannes Thumshirn
Hi,
We have problem with automatic flow control (i.e. auto RTS/CTS handshaking) in our uart driver (
men_z135_uart.c). It's probably less a technical but a problem with me understanding the API.I active the hardware auto flow control feature on the CRTSCTS flag in my
uart_ops->set_termios()function. But then the RTS flag is set on every call of theuart_ops->set_mctrl()function, this seems to confuse the hardware. Is there a way to tell the tty layer that flow control is handled solely by hardware? I.e. is there a way of telling serial core to leave out the calls to uart_set_mctrl()/uart_clear_mctrl() in uart_throttle()/uart_unthrottle(), or is settingUPF_FLOW_HARDand then implementing a dummy port->ops->{un}throttle() the correct way?
Quoted 3 lines
Are there any drivers that use a hardware's automatic flow control feature I can use as an example? A fast grep on AFE reveals some spots, but I can't really find a difference to my implementation.
uart_throttle()/uart_unthrottle() is essentially broken.
If the RTS pin is driveable, then the UART driver must respond to TIOCM_RTS set and clear in the ->set_mctrl() handler, regardless of any mode selected in termios or other mode such as autoRTS.
This requirement exists because both userspace and other kernel drivers may want to drive RTS for their own purposes.
For example, a bluetooth UART HCI may allow the bluetooth module to sleep and wakes up the module by driving RTS low for a certain length of time; if autoRTS prevents MCR writes from driving RTS, then the wake up never happens. (see drivers/bluetooth/hci_ath.c : ath_wakeup_ar3k() for the equally broken workaround of turning off CRTSCTS via an internal tty core function which is going away soon).
The reason why TI 16c750-based AFE doesn't have to bother with this is because, on that hardware, the MCR RTS bit overrides the autoRTS state; ie., RTS = MCR_RTS & autoRTS.
If your hardware treats the two states orthogonally then you'll need to turn off autoRTS mode if TIOCM_RTS is being cleared.
The amba-pl011.c driver does this; see drivers/tty/serial/amba-pl011.c:pl011_set_mctrl().
Regards,
Peter Hurley
Quoted 36 lines · Peter Hurley
Quoted 15 lines · Johannes Thumshirn
Hi,
We have problem with automatic flow control (i.e. auto RTS/CTS handshaking) in our uart driver (
men_z135_uart.c). It's probably less a technical but a problem with me understanding the API.I active the hardware auto flow control feature on the CRTSCTS flag in my
uart_ops->set_termios()function. But then the RTS flag is set on every call of theuart_ops->set_mctrl()function, this seems to confuse the hardware. Is there a way to tell the tty layer that flow control is handled solely by hardware? I.e. is there a way of telling serial core to leave out the calls to uart_set_mctrl()/uart_clear_mctrl() in uart_throttle()/uart_unthrottle(), or is settingUPF_FLOW_HARDand then implementing a dummy port->ops->{un}throttle() the correct way?Quoted 3 lines
Are there any drivers that use a hardware's automatic flow control feature I can use as an example? A fast grep on AFE reveals some spots, but I can't really find a difference to my implementation.
uart_throttle()/uart_unthrottle() is essentially broken.
If the RTS pin is driveable, then the UART driver must respond to
TIOCM_RTSset and clear in the ->set_mctrl() handler, regardless of any mode selected in termios or other mode such as autoRTS.This requirement exists because both userspace and other kernel drivers may want to drive RTS for their own purposes.
For example, a bluetooth UART HCI may allow the bluetooth module to sleep and wakes up the module by driving RTS low for a certain length of time; if autoRTS prevents MCR writes from driving RTS, then the wake up never happens. (see
drivers/bluetooth/hci_ath.c:ath_wakeup_ar3k()for the equally broken workaround of turning off CRTSCTS via an internal tty core function which is going away soon).
Quoted 8 lines
The reason why TI 16c750-based AFE doesn't have to bother with this is because, on that hardware, the MCR RTS bit overrides the autoRTS state; ie., RTS =
MCR_RTS& autoRTS.If your hardware treats the two states orthogonally then you'll need to turn off autoRTS mode if
TIOCM_RTSis being cleared.
Theamba-pl011.cdriver does this; seedrivers/tty/serial/amba-pl011.c:pl011_set_mctrl().
Thanks for the info.
We've actually found the problem. When using auto flow control we need to disable the modem status IRQs, in order to work.
The only problem that arises here is, when the modem status IRQs are disabled the uart_ops->start_tx() isn't called anymore. But there should be work arounds available.
Thanks,
Johannes
Quoted 46 lines · Johannes Thumshirn
Quoted 36 lines · Peter Hurley
Quoted 15 lines · Johannes Thumshirn
Hi,
We have problem with automatic flow control (i.e. auto RTS/CTS handshaking) in our uart driver (
men_z135_uart.c). It's probably less a technical but a problem with me understanding the API.I active the hardware auto flow control feature on the CRTSCTS flag in my
uart_ops->set_termios()function. But then the RTS flag is set on every call of theuart_ops->set_mctrl()function, this seems to confuse the hardware. Is there a way to tell the tty layer that flow control is handled solely by hardware? I.e. is there a way of telling serial core to leave out the calls to uart_set_mctrl()/uart_clear_mctrl() in uart_throttle()/uart_unthrottle(), or is settingUPF_FLOW_HARDand then implementing a dummy port->ops->{un}throttle() the correct way?Quoted 3 lines
Are there any drivers that use a hardware's automatic flow control feature I can use as an example? A fast grep on AFE reveals some spots, but I can't really find a difference to my implementation.
uart_throttle()/uart_unthrottle() is essentially broken.
If the RTS pin is driveable, then the UART driver must respond to
TIOCM_RTSset and clear in the ->set_mctrl() handler, regardless of any mode selected in termios or other mode such as autoRTS.This requirement exists because both userspace and other kernel drivers may want to drive RTS for their own purposes.
For example, a bluetooth UART HCI may allow the bluetooth module to sleep and wakes up the module by driving RTS low for a certain length of time; if autoRTS prevents MCR writes from driving RTS, then the wake up never happens. (see
drivers/bluetooth/hci_ath.c:ath_wakeup_ar3k()for the equally broken workaround of turning off CRTSCTS via an internal tty core function which is going away soon).Quoted 8 lines
The reason why TI 16c750-based AFE doesn't have to bother with this is because, on that hardware, the MCR RTS bit overrides the autoRTS state; ie., RTS =
MCR_RTS& autoRTS.If your hardware treats the two states orthogonally then you'll need to turn off autoRTS mode if
TIOCM_RTSis being cleared.
Theamba-pl011.cdriver does this; seedrivers/tty/serial/amba-pl011.c:pl011_set_mctrl().
Quoted 4 lines
Thanks for the info.
We've actually found the problem. When using auto flow control we need to disable the modem status IRQs, in order to work.
So the UART still raises modem status interrupts for DCTS when autoCTS is on?
Quoted 3 lines
The only problem that arises here is, when the modem status IRQs are disabled the
uart_ops->start_tx()isn't called anymore. But there should be work arounds available.
Almost certainly this is because ->hw_stopped has been set. The serial core does this in two places (besides uart_handle_cts_change()):uart_port_startup() after initializing the port and, in uart_set_termios(), which, if you set UPF_HARD_FLOW, the serial core will skip.
Regards,
Peter Hurley
[Note: there's been some changes to flow control for 3.18; hw_stopped was moved to uart_port].
Quoted 63 lines · Peter Hurley
Quoted 46 lines · Johannes Thumshirn
Quoted 36 lines · Peter Hurley
Quoted 15 lines · Johannes Thumshirn
Hi,
We have problem with automatic flow control (i.e. auto RTS/CTS handshaking) in our uart driver (
men_z135_uart.c). It's probably less a technical but a problem with me understanding the API.I active the hardware auto flow control feature on the CRTSCTS flag in my
uart_ops->set_termios()function. But then the RTS flag is set on every call of theuart_ops->set_mctrl()function, this seems to confuse the hardware. Is there a way to tell the tty layer that flow control is handled solely by hardware? I.e. is there a way of telling serial core to leave out the calls to uart_set_mctrl()/uart_clear_mctrl() in uart_throttle()/uart_unthrottle(), or is settingUPF_FLOW_HARDand then implementing a dummy port->ops->{un}throttle() the correct way?Quoted 3 lines
Are there any drivers that use a hardware's automatic flow control feature I can use as an example? A fast grep on AFE reveals some spots, but I can't really find a difference to my implementation.
uart_throttle()/uart_unthrottle() is essentially broken.
If the RTS pin is driveable, then the UART driver must respond to
TIOCM_RTSset and clear in the ->set_mctrl() handler, regardless of any mode selected in termios or other mode such as autoRTS.This requirement exists because both userspace and other kernel drivers may want to drive RTS for their own purposes.
For example, a bluetooth UART HCI may allow the bluetooth module to sleep and wakes up the module by driving RTS low for a certain length of time; if autoRTS prevents MCR writes from driving RTS, then the wake up never happens. (see
drivers/bluetooth/hci_ath.c:ath_wakeup_ar3k()for the equally broken workaround of turning off CRTSCTS via an internal tty core function which is going away soon).Quoted 8 lines
The reason why TI 16c750-based AFE doesn't have to bother with this is because, on that hardware, the MCR RTS bit overrides the autoRTS state; ie., RTS =
MCR_RTS& autoRTS.If your hardware treats the two states orthogonally then you'll need to turn off autoRTS mode if
TIOCM_RTSis being cleared.
Theamba-pl011.cdriver does this; seedrivers/tty/serial/amba-pl011.c:pl011_set_mctrl().Quoted 4 lines
Thanks for the info.
We've actually found the problem. When using auto flow control we need to disable the modem status IRQs, in order to work.
So the UART still raises modem status interrupts for DCTS when autoCTS is on?
Quoted 3 lines
The only problem that arises here is, when the modem status IRQs are disabled the
uart_ops->start_tx()isn't called anymore. But there should be work arounds available.Almost certainly this is because ->hw_stopped has been set. The serial core does this in two places (besides
uart_handle_cts_change()):uart_port_startup()after initializing the port and, inuart_set_termios(), which, if you setUPF_HARD_FLOW, the serial core will skip.
Quoted 6 lines
Regards,
Peter Hurley[Note: there's been some changes to flow control for 3.18;
hw_stoppedwas moved touart_port].
Sorry for the late reply, I've been a bit busy.
We've found a solution to the problem and I'll post a patch for review in a few days.
Thanks again,
Johannes