]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/suse-2.6.27.39/patches.fixes/hpet-correct-periodic-intr.patch
Fix oinkmaster patch.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.fixes / hpet-correct-periodic-intr.patch
1 From: Nils Carlson <nils.carlson@ericsson.com>
2 Subject: hpet: hpet driver periodic timer setup bug fixes
3 References: bnc#515640
4 Patch-mainline: queued
5
6
7 The periodic interrupt from drivers/char/hpet.c does not work correctly,
8 both when using the periodic capability of the hardware and while
9 emulating the periodic interrupt (when hardware does not support
10 periodic mode).
11
12 With timers capable of periodic interrupts, the comparator field is first
13 set with the period value followed by set of hidden accumulator,
14 which has the side effect of overwriting the comparator value. This
15 results in wrong periodicity for the interrupts. For,
16 periodic interrupts to work, following steps are necessary, in that order.
17 * Set config with Tn_VAL_SET_CNF bit
18 * Write to hidden accumulator, the value written is the time when the
19 first interrupt should be generated
20 * Write compartor with period interval for subsequent interrupts
21 (http://www.intel.com/hardwaredesign/hpetspec_1.pdf )
22
23 When emulating periodic timer with timers not capable of periodic
24 interrupt, driver is adding the period to counter value instead of
25 comparator value, which causes slow drift when using this emulation.
26
27 Also, driver seems to add hpetp->hp_delta both while setting up
28 periodic interrupt and while emulating periodic interrupts with timers
29 not capable of doing periodic interrupts. This hp_delta will result in
30 slower than expected interrupt rate and should not be used while setting
31 the interval.
32
33 Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
34 Signed-off-by: Nils Carlson <nils.carlson@ericsson.com>
35 Acked-by: Goldwyn Rodrigues <rgoldwyn@suse.de>
36
37 ---
38 drivers/char/hpet.c | 23 ++++++++++++++++-------
39 1 file changed, 16 insertions(+), 7 deletions(-)
40
41 Index: linux-2.6.27-SLE11_BRANCH/drivers/char/hpet.c
42 ===================================================================
43 --- linux-2.6.27-SLE11_BRANCH.orig/drivers/char/hpet.c 2008-10-09 17:13:53.000000000 -0500
44 +++ linux-2.6.27-SLE11_BRANCH/drivers/char/hpet.c 2009-08-28 09:58:42.000000000 -0500
45 @@ -164,9 +164,9 @@ static irqreturn_t hpet_interrupt(int ir
46 unsigned long m, t;
47
48 t = devp->hd_ireqfreq;
49 - m = read_counter(&devp->hd_hpet->hpet_mc);
50 - write_counter(t + m + devp->hd_hpets->hp_delta,
51 - &devp->hd_timer->hpet_compare);
52 + m = read_counter(&devp->hd_timer->hpet_compare);
53 + write_counter(t + m, &devp->hd_timer->hpet_compare);
54 +
55 }
56
57 if (devp->hd_flags & HPET_SHARED_IRQ)
58 @@ -444,15 +444,24 @@ static int hpet_ioctl_ieon(struct hpet_d
59 g = v | Tn_INT_ENB_CNF_MASK;
60
61 if (devp->hd_flags & HPET_PERIODIC) {
62 - write_counter(t, &timer->hpet_compare);
63 g |= Tn_TYPE_CNF_MASK;
64 - v |= Tn_TYPE_CNF_MASK;
65 - writeq(v, &timer->hpet_config);
66 - v |= Tn_VAL_SET_CNF_MASK;
67 + v |= Tn_TYPE_CNF_MASK | Tn_VAL_SET_CNF_MASK;
68 writeq(v, &timer->hpet_config);
69 local_irq_save(flags);
70 + /*
71 + * NOTE: First we modify the hidden accumulator
72 + * register supported by periodic-capable comparators.
73 + * We never want to modify the (single) counter; that
74 + * would affect all the comparators. The value written
75 + * is the counter value when the first interrupt is due.
76 + */
77 m = read_counter(&hpet->hpet_mc);
78 write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
79 + /*
80 + * Then we modify the comparator, indicating the period
81 + * for subsequent interrupt.
82 + */
83 + write_counter(t, &timer->hpet_compare);
84 } else {
85 local_irq_save(flags);
86 m = read_counter(&hpet->hpet_mc);