| From ce094de5b4d0ce7a33f290b33f504c3ef92c575f Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> |
| Date: Tue, 24 Sep 2013 21:26:20 +0300 |
| Subject: drm/i915: Make vlv_find_best_dpll() ppm calculation safe |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| 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> |
| (cherry picked from commit 69e4f900be175fd80fe69221a329c8993b16925b) |
| Signed-off-by: Darren Hart <dvhart@linux.intel.com> |
| --- |
| drivers/gpu/drm/i915/intel_display.c | 16 ++++++++-------- |
| 1 file changed, 8 insertions(+), 8 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c |
| index 1759e4c469e6..5b95e2a42caa 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) { |
| -- |
| 1.8.5.rc3 |
| |