summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2014-03-13 18:25:56 -0400
committerDave Airlie <airlied@redhat.com>2014-03-14 10:36:46 +1000
commit0789f3f2799e6497e9e2e7488da679c03b7fa468 (patch)
treef13653fa738e292241d060009bc93e42a5518d70
parent62ba63f687d7b99aff7c88ffd2774f15a2471ce0 (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>
-rw-r--r--src/mga_driver.c12
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);