mirror of
https://github.com/torvalds/linux.git
synced 2024-12-11 05:33:09 +00:00
drm/mgag200: fix G200ER pll picking algorithm
The original code was misported from the X driver, a) an int went to unsigned int, breaking the downward counting testm code b) the port did the vco/computed clock bits completely wrong. This fixes an infinite loop on modprobe on some Dell servers with the G200ER chipset variant. Found in internal testing. Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
f7b83b908f
commit
9830605d4c
@ -468,10 +468,11 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock)
|
||||
{
|
||||
unsigned int vcomax, vcomin, pllreffreq;
|
||||
unsigned int delta, tmpdelta;
|
||||
unsigned int testr, testn, testm, testo;
|
||||
int testr, testn, testm, testo;
|
||||
unsigned int p, m, n;
|
||||
unsigned int computed;
|
||||
unsigned int computed, vco;
|
||||
int tmp;
|
||||
const unsigned int m_div_val[] = { 1, 2, 4, 8 };
|
||||
|
||||
m = n = p = 0;
|
||||
vcomax = 1488000;
|
||||
@ -490,12 +491,13 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock)
|
||||
if (delta == 0)
|
||||
break;
|
||||
for (testo = 5; testo < 33; testo++) {
|
||||
computed = pllreffreq * (testn + 1) /
|
||||
vco = pllreffreq * (testn + 1) /
|
||||
(testr + 1);
|
||||
if (computed < vcomin)
|
||||
if (vco < vcomin)
|
||||
continue;
|
||||
if (computed > vcomax)
|
||||
if (vco > vcomax)
|
||||
continue;
|
||||
computed = vco / (m_div_val[testm] * (testo + 1));
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user