Browse Source

MIPS: hpet: Increase HPET_MIN_PROG_DELTA and decrease HPET_MIN_CYCLES

At first, we prefer to use mips clockevent device, so we decrease the
rating of hpet clockevent device.

For hpet, if HPET_MIN_PROG_DELTA (minimum delta of hpet programming) is
too small and HPET_MIN_CYCLES (threshold of -ETIME checking) is too
large, then hpet_next_event() can easily return -ETIME. After commit
c6eb3f70d44828 ("hrtimer: Get rid of hrtimer softirq") this will cause
a RCU stall.

So, HPET_MIN_PROG_DELTA must be sufficient that we don't re-trip the
-ETIME check -- if we do, we will return -ETIME, forward the next event
time, try to set it, return -ETIME again, and basically lock the system
up. Meanwhile, HPET_MIN_CYCLES doesn't need to be too large, 16 cycles
is enough.

This solution is similar to commit f9eccf24615672 ("clocksource/drivers
/vt8500: Increase the minimum delta").

By the way, this patch ensures hpet count/compare to be 32-bit long.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Cc: John Crispin <john@phrozen.org>
Cc: Steven J . Hill <Steven.Hill@imgtec.com>
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: linux-mips@linux-mips.org
Cc: stable@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/13819/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Huacai Chen 9 years ago
parent
commit
3ef0665398
1 changed files with 7 additions and 7 deletions
  1. 7 7
      arch/mips/loongson64/loongson-3/hpet.c

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

@@ -13,8 +13,8 @@
 #define SMBUS_PCI_REG64		0x64
 #define SMBUS_PCI_REG64		0x64
 #define SMBUS_PCI_REGB4		0xb4
 #define SMBUS_PCI_REGB4		0xb4
 
 
-#define HPET_MIN_CYCLES		64
-#define HPET_MIN_PROG_DELTA	(HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1))
+#define HPET_MIN_CYCLES		16
+#define HPET_MIN_PROG_DELTA	(HPET_MIN_CYCLES * 12)
 
 
 static DEFINE_SPINLOCK(hpet_lock);
 static DEFINE_SPINLOCK(hpet_lock);
 DEFINE_PER_CPU(struct clock_event_device, hpet_clockevent_device);
 DEFINE_PER_CPU(struct clock_event_device, hpet_clockevent_device);
@@ -157,14 +157,14 @@ static int hpet_tick_resume(struct clock_event_device *evt)
 static int hpet_next_event(unsigned long delta,
 static int hpet_next_event(unsigned long delta,
 		struct clock_event_device *evt)
 		struct clock_event_device *evt)
 {
 {
-	unsigned int cnt;
-	int res;
+	u32 cnt;
+	s32 res;
 
 
 	cnt = hpet_read(HPET_COUNTER);
 	cnt = hpet_read(HPET_COUNTER);
-	cnt += delta;
+	cnt += (u32) delta;
 	hpet_write(HPET_T0_CMP, cnt);
 	hpet_write(HPET_T0_CMP, cnt);
 
 
-	res = (int)(cnt - hpet_read(HPET_COUNTER));
+	res = (s32)(cnt - hpet_read(HPET_COUNTER));
 
 
 	return res < HPET_MIN_CYCLES ? -ETIME : 0;
 	return res < HPET_MIN_CYCLES ? -ETIME : 0;
 }
 }
@@ -230,7 +230,7 @@ void __init setup_hpet_timer(void)
 
 
 	cd = &per_cpu(hpet_clockevent_device, cpu);
 	cd = &per_cpu(hpet_clockevent_device, cpu);
 	cd->name = "hpet";
 	cd->name = "hpet";
-	cd->rating = 320;
+	cd->rating = 100;
 	cd->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
 	cd->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
 	cd->set_state_shutdown = hpet_set_state_shutdown;
 	cd->set_state_shutdown = hpet_set_state_shutdown;
 	cd->set_state_periodic = hpet_set_state_periodic;
 	cd->set_state_periodic = hpet_set_state_periodic;