linux/drivers/char
Nils Carlson 273ef9509b drivers/char/hpet.c: fix periodic-emulation for delayed interrupts
When interrupts are delayed due to interrupt masking or due to other
interrupts being serviced the HPET periodic-emuation would fail.  This
happened because given an interval t and a time for the current interrupt
m we would compute the next time as t + m.  This works until we are
delayed for > t, in which case we would be writing a new value which is in
fact in the past.

This can be solved by computing the next time instead as (k * t) + m where
k is large enough to be in the future.  The exact computation of k is
described in a comment to the code.

More detail:

Assuming an interval of 5 between each expected interrupt we have a normal
case of

t0: interrupt, read t0 from comparator, set next interrupt t0 + 5
t5: interrupt, read t5 from comparator, set next interrupt t5 + 5
t10: interrupt, read t10 from comparator, set next interrupt t10 + 5
...

So, what happens when the interrupt is serviced too late?

t0: interrupt, read t0 from comparator, set next interrupt t0 + 5
t11: delayed interrupt serviced, read t5 from comparator, set next
interrupt t5 + 5, which is in the past!
... counter loops ...
t10: Much much later, get the next interrupt.

This can happen either because we have interrupts masked for too long
(some stupid driver goes on a printk rampage) or just because we are
pushing the limits of the interval (too small a period), or both most
probably.

My solution is to read the main counter as well and set the next interrupt
to occur at the right interval, for example:

t0: interrupt, read t0 from comparator, set next interrupt t0 + 5
t11: delayed interrupt serviced, read t5 from comparator, set next
interrupt t15 as t10 has been missed.
t15: back on track.

Signed-off-by: Nils Carlson <nils.carlson@ericsson.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-06-15 20:04:02 -07:00
..
agp
hw_random
ipmi ipmi: convert to seq_file interface 2011-05-26 17:12:37 -07:00
mwave
pcmcia
tpm
xilinx_hwicap
apm-emulation.c apm-emulation: apm_mutex breaks ACK; remove it 2011-05-23 12:50:43 +02:00
applicom.c
applicom.h
bfin-otp.c
briq_panel.c
bsr.c
ds1302.c
ds1620.c
dsp56k.c
dtlk.c
efirtc.c
generic_nvram.c
genrtc.c
hangcheck-timer.c
hpet.c drivers/char/hpet.c: fix periodic-emulation for delayed interrupts 2011-06-15 20:04:02 -07:00
i8k.c i8k: Integrate with the hwmon subsystem 2011-05-25 20:43:33 +02:00
Kconfig
lp.c
Makefile
mbcs.c
mbcs.h
mem.c
misc.c
mmtimer.c
msm_smd_pkt.c
mspec.c drivers/char/mspec.c: use {k,v}zalloc to allocate memory 2011-05-26 17:12:37 -07:00
nsc_gpio.c
nvram.c
nwbutton.c
nwbutton.h
nwflash.c
pc8736x_gpio.c
ppdev.c drivers/char/ppdev.c: put gotten port value 2011-05-26 17:12:37 -07:00
ps3flash.c
ramoops.c
random.c
raw.c
rtc.c
scc.h
scx200_gpio.c
snsc_event.c
snsc.c
snsc.h
sonypi.c
tb0219.c
tlclk.c
toshiba.c
ttyprintk.c
uv_mmtimer.c
viotape.c
virtio_console.c virtio console: don't manually set or finalize VIRTIO_CONSOLE_F_MULTIPORT. 2011-05-30 11:14:13 +09:30