linux/drivers/tty
Phil Elwell 8344498721 sc16is7xx: Fix for multi-channel stall
The SC16IS752 is a dual-channel device. The two channels are largely
independent, but the IRQ signals are wired together as an open-drain,
active low signal which will be driven low while either of the
channels requires attention, which can be for significant periods of
time until operations complete and the interrupt can be acknowledged.
In that respect it is should be treated as a true level-sensitive IRQ.

The kernel, however, needs to be able to exit interrupt context in
order to use I2C or SPI to access the device registers (which may
involve sleeping).  Therefore the interrupt needs to be masked out or
paused in some way.

The usual way to manage sleeping from within an interrupt handler
is to use a threaded interrupt handler - a regular interrupt routine
does the minimum amount of work needed to triage the interrupt before
waking the interrupt service thread. If the threaded IRQ is marked as
IRQF_ONESHOT the kernel will automatically mask out the interrupt
until the thread runs to completion. The sc16is7xx driver used to
use a threaded IRQ, but a patch switched to using a kthread_worker
in order to set realtime priorities on the handler thread and for
other optimisations. The end result is non-threaded IRQ that
schedules some work then returns IRQ_HANDLED, making the kernel
think that all IRQ processing has completed.

The work-around to prevent a constant stream of interrupts is to
mark the interrupt as edge-sensitive rather than level-sensitive,
but interpreting an active-low source as a falling-edge source
requires care to prevent a total cessation of interrupts. Whereas
an edge-triggering source will generate a new edge for every interrupt
condition a level-triggering source will keep the signal at the
interrupting level until it no longer requires attention; in other
words, the host won't see another edge until all interrupt conditions
are cleared. It is therefore vital that the interrupt handler does not
exit with an outstanding interrupt condition, otherwise the kernel
will not receive another interrupt unless some other operation causes
the interrupt state on the device to be cleared.

The existing sc16is7xx driver has a very simple interrupt "thread"
(kthread_work job) that processes interrupts on each channel in turn
until there are no more. If both channels are active and the first
channel starts interrupting while the handler for the second channel
is running then it will not be detected and an IRQ stall ensues. This
could be handled easily if there was a shared IRQ status register, or
a convenient way to determine if the IRQ had been deasserted for any
length of time, but both appear to be lacking.

Avoid this problem (or at least make it much less likely to happen)
by reducing the granularity of per-channel interrupt processing
to one condition per iteration, only exiting the overall loop when
both channels are no longer interrupting.

Signed-off-by: Phil Elwell <phil@raspberrypi.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2018-09-18 16:07:25 +02:00
..
hvc tty: hvc: hvc_write() fix break condition 2018-09-10 18:04:31 +02:00
ipwireless tty: ipwireless: Replace GFP_ATOMIC with GFP_KERNEL in ipwireless_network_create 2018-04-23 10:57:06 +02:00
serdev serdev: add dev_pm_domain_attach|detach() 2018-07-15 12:23:53 +02:00
serial sc16is7xx: Fix for multi-channel stall 2018-09-18 16:07:25 +02:00
vt TTY/Serial driver patches for 4.19-rc1 2018-08-18 10:50:41 -07:00
amiserial.c tty: replace ->proc_fops with ->proc_show 2018-05-16 07:24:30 +02:00
cyclades.c tty: replace ->proc_fops with ->proc_show 2018-05-16 07:24:30 +02:00
ehv_bytechan.c tty: Convert to using %pOFn instead of device_node.name 2018-09-18 16:07:25 +02:00
goldfish.c headers: separate linux/mod_devicetable.h from linux/platform_device.h 2018-07-07 17:52:26 +02:00
isicom.c treewide: kmalloc() -> kmalloc_array() 2018-06-12 16:19:22 -07:00
Kconfig Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux 2018-04-09 09:04:10 -07:00
Makefile tty: remove bfin_jtag_comm and hvc_bfin_jtag drivers 2018-03-26 15:57:24 +02:00
mips_ejtag_fdc.c tty: Remove redundant license text 2017-11-08 13:08:12 +01:00
moxa.c tty: moxa: Add support for CMSPAR 2017-11-28 15:32:33 +01:00
moxa.h tty: moxa: Add support for CMSPAR 2017-11-28 15:32:33 +01:00
mxser.c tty: Remove redundant license text 2017-11-08 13:08:12 +01:00
mxser.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
n_gsm.c Merge 4.17-rc3 into tty-next 2018-04-30 05:14:55 -07:00
n_hdlc.c vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
n_null.c tty: Remove redundant license text 2017-11-08 13:08:12 +01:00
n_r3964.c vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
n_tracerouter.c tty: Remove redundant license text 2017-11-08 13:08:12 +01:00
n_tracesink.c tty: Remove redundant license text 2017-11-08 13:08:12 +01:00
n_tracesink.h tty: Remove redundant license text 2017-11-08 13:08:12 +01:00
n_tty.c n_tty: Access echo_* variables carefully. 2018-06-28 21:30:16 +09:00
nozomi.c tty/nozomi: fix inconsistent indentation 2018-04-25 14:54:26 +02:00
pty.c pty: fix O_CLOEXEC for TIOCGPTPEER 2018-07-21 09:08:47 +02:00
rocket_int.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
rocket.c tty: rocket: Fix possible buffer overwrite on register_PCI 2018-08-02 10:11:32 +02:00
rocket.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
synclink_gt.c tty: replace ->proc_fops with ->proc_show 2018-05-16 07:24:30 +02:00
synclink.c tty: replace ->proc_fops with ->proc_show 2018-05-16 07:24:30 +02:00
synclinkmp.c tty: replace ->proc_fops with ->proc_show 2018-05-16 07:24:30 +02:00
sysrq.c signal: Pass pid type into do_send_sig_info 2018-07-21 12:57:35 -05:00
tty_audit.c audit: eliminate audit_enabled magic number comparison 2018-06-19 10:43:55 -04:00
tty_baudrate.c tty: support CIBAUD without BOTHER 2018-07-16 12:00:43 +02:00
tty_buffer.c tty: add SPDX identifiers to all remaining files in drivers/tty/ 2017-11-08 13:08:12 +01:00
tty_io.c Merge branch 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace 2018-08-21 13:47:29 -07:00
tty_ioctl.c tty: add missing const to termios hw-change helper 2018-05-22 10:08:05 +02:00
tty_jobctrl.c tty: add SPDX identifiers to all remaining files in drivers/tty/ 2017-11-08 13:08:12 +01:00
tty_ldisc.c proc: introduce proc_create_seq{,_data} 2018-05-16 07:23:35 +02:00
tty_ldsem.c atomic/tty: Fix up atomic abuse in ldsem 2018-06-28 21:07:55 +09:00
tty_mutex.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
tty_port.c tty: add SPDX identifiers to all remaining files in drivers/tty/ 2017-11-08 13:08:12 +01:00
vcc.c tty: vcc: Convert timers to use timer_setup() 2017-11-04 12:01:54 +01:00