@@ -33,29 +33,64 @@ struct ce_unbind {
3333 int res ;
3434};
3535
36- /**
37- * clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds
38- * @latch: value to convert
39- * @evt: pointer to clock event device descriptor
40- *
41- * Math helper, returns latch value converted to nanoseconds (bound checked)
42- */
43- u64 clockevent_delta2ns (unsigned long latch , struct clock_event_device * evt )
36+ static u64 cev_delta2ns (unsigned long latch , struct clock_event_device * evt ,
37+ bool ismax )
4438{
4539 u64 clc = (u64 ) latch << evt -> shift ;
40+ u64 rnd ;
4641
4742 if (unlikely (!evt -> mult )) {
4843 evt -> mult = 1 ;
4944 WARN_ON (1 );
5045 }
46+ rnd = (u64 ) evt -> mult - 1 ;
47+
48+ /*
49+ * Upper bound sanity check. If the backwards conversion is
50+ * not equal latch, we know that the above shift overflowed.
51+ */
52+ if ((clc >> evt -> shift ) != (u64 )latch )
53+ clc = ~0ULL ;
54+
55+ /*
56+ * Scaled math oddities:
57+ *
58+ * For mult <= (1 << shift) we can safely add mult - 1 to
59+ * prevent integer rounding loss. So the backwards conversion
60+ * from nsec to device ticks will be correct.
61+ *
62+ * For mult > (1 << shift), i.e. device frequency is > 1GHz we
63+ * need to be careful. Adding mult - 1 will result in a value
64+ * which when converted back to device ticks can be larger
65+ * than latch by up to (mult - 1) >> shift. For the min_delta
66+ * calculation we still want to apply this in order to stay
67+ * above the minimum device ticks limit. For the upper limit
68+ * we would end up with a latch value larger than the upper
69+ * limit of the device, so we omit the add to stay below the
70+ * device upper boundary.
71+ *
72+ * Also omit the add if it would overflow the u64 boundary.
73+ */
74+ if ((~0ULL - clc > rnd ) &&
75+ (!ismax || evt -> mult <= (1U << evt -> shift )))
76+ clc += rnd ;
5177
5278 do_div (clc , evt -> mult );
53- if (clc < 1000 )
54- clc = 1000 ;
55- if (clc > KTIME_MAX )
56- clc = KTIME_MAX ;
5779
58- return clc ;
80+ /* Deltas less than 1usec are pointless noise */
81+ return clc > 1000 ? clc : 1000 ;
82+ }
83+
84+ /**
85+ * clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds
86+ * @latch: value to convert
87+ * @evt: pointer to clock event device descriptor
88+ *
89+ * Math helper, returns latch value converted to nanoseconds (bound checked)
90+ */
91+ u64 clockevent_delta2ns (unsigned long latch , struct clock_event_device * evt )
92+ {
93+ return cev_delta2ns (latch , evt , false);
5994}
6095EXPORT_SYMBOL_GPL (clockevent_delta2ns );
6196
@@ -380,8 +415,8 @@ void clockevents_config(struct clock_event_device *dev, u32 freq)
380415 sec = 600 ;
381416
382417 clockevents_calc_mult_shift (dev , freq , sec );
383- dev -> min_delta_ns = clockevent_delta2ns (dev -> min_delta_ticks , dev );
384- dev -> max_delta_ns = clockevent_delta2ns (dev -> max_delta_ticks , dev );
418+ dev -> min_delta_ns = cev_delta2ns (dev -> min_delta_ticks , dev , false );
419+ dev -> max_delta_ns = cev_delta2ns (dev -> max_delta_ticks , dev , true );
385420}
386421
387422/**
0 commit comments