Skip to content

Commit e76f100

Browse files
chenhuacaigregkh
authored andcommitted
MIPS: hpet: Choose a safe value for the ETIME check
commit 5610b12 upstream. This patch is borrowed from x86 hpet driver and explaind below: Due to the overly intelligent design of HPETs, we need to workaround the problem that the compare value which we write is already behind the actual counter value at the point where the value hits the real compare register. This happens for two reasons: 1) We read out the counter, add the delta and write the result to the compare register. When a NMI hits between the read out and the write then the counter can be ahead of the event already. 2) The write to the compare register is delayed by up to two HPET cycles in AMD chipsets. We can work around this by reading back the compare register to make sure that the written value has hit the hardware. But that is bad performance wise for the normal case where the event is far enough in the future. As we already know that the write can be delayed by up to two cycles we can avoid the read back of the compare register completely if we make the decision whether the delta has elapsed already or not based on the following calculation: cmp = event - actual_count; If cmp is less than 64 HPET clock cycles, then we decide that the event has happened already and return -ETIME. That covers the above #1 and #2 problems which would cause a wait for HPET wraparound (~306 seconds). Signed-off-by: Huacai Chen <[email protected]> Cc: Aurelien Jarno <[email protected]> Cc: Steven J. Hill <[email protected]> Cc: Fuxin Zhang <[email protected]> Cc: Zhangjin Wu <[email protected]> Cc: Huacai Chen <[email protected]> Cc: [email protected] Patchwork: https://patchwork.linux-mips.org/patch/12162/ Signed-off-by: Ralf Baechle <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 332e40d commit e76f100

File tree

1 file changed

+7
-3
lines changed
  • arch/mips/loongson64/loongson-3

1 file changed

+7
-3
lines changed

arch/mips/loongson64/loongson-3/hpet.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
#define SMBUS_PCI_REG64 0x64
1414
#define SMBUS_PCI_REGB4 0xb4
1515

16+
#define HPET_MIN_CYCLES 64
17+
#define HPET_MIN_PROG_DELTA (HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1))
18+
1619
static DEFINE_SPINLOCK(hpet_lock);
1720
DEFINE_PER_CPU(struct clock_event_device, hpet_clockevent_device);
1821

@@ -161,8 +164,9 @@ static int hpet_next_event(unsigned long delta,
161164
cnt += delta;
162165
hpet_write(HPET_T0_CMP, cnt);
163166

164-
res = ((int)(hpet_read(HPET_COUNTER) - cnt) > 0) ? -ETIME : 0;
165-
return res;
167+
res = (int)(cnt - hpet_read(HPET_COUNTER));
168+
169+
return res < HPET_MIN_CYCLES ? -ETIME : 0;
166170
}
167171

168172
static irqreturn_t hpet_irq_handler(int irq, void *data)
@@ -237,7 +241,7 @@ void __init setup_hpet_timer(void)
237241
cd->cpumask = cpumask_of(cpu);
238242
clockevent_set_clock(cd, HPET_FREQ);
239243
cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
240-
cd->min_delta_ns = 5000;
244+
cd->min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA, cd);
241245

242246
clockevents_register_device(cd);
243247
setup_irq(HPET_T0_IRQ, &hpet_irq);

0 commit comments

Comments
 (0)