diff options
author | Mikulas Patocka <mpatocka@redhat.com> | 2014-03-13 18:25:56 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-03-14 10:36:46 +1000 |
commit | 0789f3f2799e6497e9e2e7488da679c03b7fa468 (patch) | |
tree | f13653fa738e292241d060009bc93e42a5518d70 /src/mga_driver.c | |
parent | 62ba63f687d7b99aff7c88ffd2774f15a2471ce0 (diff) |
xf86-video-mga: fix a lockup in the mga driver
I've had a Xserver lockup in the mga driver, examining it with gdb showed
this obviously broken loop:
count = INREG(MGAREG_VCOUNT) + 2;
while(INREG(MGAREG_VCOUNT) < count);
It reads the line counter and waits until the counter advances by two. The
cause of the lockup is this - if the kernel reschedules the Xorg process
and lets it run in such a moment when INREG(MGAREG_VCOUNT) returns the
maximum (or maximum minus 1) line count, the loop never exits.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'src/mga_driver.c')
-rw-r--r-- | src/mga_driver.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/src/mga_driver.c b/src/mga_driver.c index f0b5abb..177a5a7 100644 --- a/src/mga_driver.c +++ b/src/mga_driver.c @@ -3618,7 +3618,7 @@ void MGAAdjustFrame(ADJUST_FRAME_ARGS_DECL) { SCRN_INFO_PTR(arg); - int Base, tmp, count; + int Base, tmp, count, last_vcount; MGAFBLayout *pLayout; MGAPtr pMga; @@ -3648,8 +3648,14 @@ MGAAdjustFrame(ADJUST_FRAME_ARGS_DECL) while (INREG8(0x1FDA) & 0x08); while (!(INREG8(0x1FDA) & 0x08)); /* wait until we're past the start (fixseg.c in the DDK) */ - count = INREG(MGAREG_VCOUNT) + 2; - while(INREG(MGAREG_VCOUNT) < count); + last_vcount = INREG(MGAREG_VCOUNT); + count = last_vcount + 2; + while (1) { + int vcount = INREG(MGAREG_VCOUNT); + if (vcount >= count) break; + if (vcount < last_vcount) break; + last_vcount = count; + } OUTREG16(MGAREG_CRTC_INDEX, (Base & 0x00FF00) | 0x0C); OUTREG16(MGAREG_CRTC_INDEX, ((Base & 0x0000FF) << 8) | 0x0D); |