diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2013-09-24 21:26:20 +0300 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-10-10 12:46:50 +0200 |
commit | 69e4f900be175fd80fe69221a329c8993b16925b (patch) | |
tree | d7e2454313d8e1577f8645aa3f89186985558f66 /drivers/gpu/drm/i915/intel_display.c | |
parent | 953d22e870e2f15963976c77985b263afcceafc9 (diff) | |
download | lwn-69e4f900be175fd80fe69221a329c8993b16925b.tar.gz lwn-69e4f900be175fd80fe69221a329c8993b16925b.zip |
drm/i915: Make vlv_find_best_dpll() ppm calculation safe
Use div_u64() to make the ppm calculation in vlv_find_best_dpll() safe
against interger overflows.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 16 |
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 617b963dfb67..dc5077560c74 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -672,13 +672,11 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, u32 p1, p2, m1, m2, vco, bestn, bestm1, bestm2, bestp1, bestp2; u32 m, n, fastclk; u32 updrate, minupdate, p; - unsigned long bestppm, ppm, absppm; + unsigned int bestppm = 1000000; int dotclk, flag; flag = 0; dotclk = target * 1000; - bestppm = 1000000; - ppm = absppm = 0; fastclk = dotclk / (2*100); updrate = 0; minupdate = 19200; @@ -695,6 +693,8 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, p = p1 * p2; /* based on hardware requirement, prefer bigger m1,m2 values */ for (m1 = limit->m1.min; m1 <= limit->m1.max; m1++) { + unsigned int ppm, diff; + m2 = DIV_ROUND_CLOSEST(fastclk * p * n, refclk * m1); m = m1 * m2; vco = updrate * m; @@ -702,14 +702,14 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, if (vco < limit->vco.min || vco >= limit->vco.max) continue; - ppm = 1000000 * ((vco / p) - fastclk) / fastclk; - absppm = (ppm > 0) ? ppm : (-ppm); - if (absppm < 100 && ((p1 * p2) > (bestp1 * bestp2))) { + diff = abs(vco / p - fastclk); + ppm = div_u64(1000000ULL * diff, fastclk); + if (ppm < 100 && ((p1 * p2) > (bestp1 * bestp2))) { bestppm = 0; flag = 1; } - if (absppm < bestppm - 10) { - bestppm = absppm; + if (ppm < bestppm - 10) { + bestppm = ppm; flag = 1; } if (flag) { |