]>
Commit | Line | Data |
---|---|---|
9f934a63 GKH |
1 | From 96e9694df446d1154ec2f4fdba8908588b9cba38 Mon Sep 17 00:00:00 2001 |
2 | From: Clemens Ladisch <clemens@ladisch.de> | |
3 | Date: Tue, 26 Oct 2010 14:22:13 -0700 | |
4 | Subject: hpet: fix unwanted interrupt due to stale irq status bit | |
5 | ||
6 | From: Clemens Ladisch <clemens@ladisch.de> | |
7 | ||
8 | commit 96e9694df446d1154ec2f4fdba8908588b9cba38 upstream. | |
9 | ||
10 | Jaswinder Singh Rajput wrote: | |
11 | > By executing Documentation/timers/hpet_example.c | |
12 | > | |
13 | > for polling, I requested for 3 iterations but it seems iteration work | |
14 | > for only 2 as first expired time is always very small. | |
15 | > | |
16 | > # ./hpet_example poll /dev/hpet 10 3 | |
17 | > -hpet: executing poll | |
18 | > hpet_poll: info.hi_flags 0x0 | |
19 | > hpet_poll: expired time = 0x13 | |
20 | > hpet_poll: revents = 0x1 | |
21 | > hpet_poll: data 0x1 | |
22 | > hpet_poll: expired time = 0x1868c | |
23 | > hpet_poll: revents = 0x1 | |
24 | > hpet_poll: data 0x1 | |
25 | > hpet_poll: expired time = 0x18645 | |
26 | > hpet_poll: revents = 0x1 | |
27 | > hpet_poll: data 0x1 | |
28 | ||
29 | Clearing the HPET interrupt enable bit disables interrupt generation | |
30 | but does not disable the timer, so the interrupt status bit will still | |
31 | be set when the timer elapses. If another interrupt arrives before | |
32 | the timer has been correctly programmed (due to some other device on | |
33 | the same interrupt line, or CONFIG_DEBUG_SHIRQ), this results in an | |
34 | extra unwanted interrupt event because the status bit is likely to be | |
35 | set from comparator matches that happened before the device was opened. | |
36 | ||
37 | Therefore, we have to ensure that the interrupt status bit is and | |
38 | stays cleared until we actually program the timer. | |
39 | ||
40 | Signed-off-by: Clemens Ladisch <clemens@ladisch.de> | |
41 | Reported-by: Jaswinder Singh Rajput <jaswinderlinux@gmail.com> | |
42 | Cc: Ingo Molnar <mingo@elte.hu> | |
43 | Cc: Thomas Gleixner <tglx@linutronix.de> | |
44 | Cc: john stultz <johnstul@us.ibm.com> | |
45 | Cc: Bob Picco <bpicco@redhat.com> | |
46 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | |
47 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
48 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
49 | ||
50 | --- | |
51 | drivers/char/hpet.c | 15 +++++++++++++++ | |
52 | 1 file changed, 15 insertions(+) | |
53 | ||
54 | --- a/drivers/char/hpet.c | |
55 | +++ b/drivers/char/hpet.c | |
56 | @@ -479,6 +479,21 @@ static int hpet_ioctl_ieon(struct hpet_d | |
57 | if (irq) { | |
58 | unsigned long irq_flags; | |
59 | ||
60 | + if (devp->hd_flags & HPET_SHARED_IRQ) { | |
61 | + /* | |
62 | + * To prevent the interrupt handler from seeing an | |
63 | + * unwanted interrupt status bit, program the timer | |
64 | + * so that it will not fire in the near future ... | |
65 | + */ | |
66 | + writel(readl(&timer->hpet_config) & ~Tn_TYPE_CNF_MASK, | |
67 | + &timer->hpet_config); | |
68 | + write_counter(read_counter(&hpet->hpet_mc), | |
69 | + &timer->hpet_compare); | |
70 | + /* ... and clear any left-over status. */ | |
71 | + isr = 1 << (devp - devp->hd_hpets->hp_dev); | |
72 | + writel(isr, &hpet->hpet_isr); | |
73 | + } | |
74 | + | |
75 | sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev)); | |
76 | irq_flags = devp->hd_flags & HPET_SHARED_IRQ | |
77 | ? IRQF_SHARED : IRQF_DISABLED; |