diff options
author | Dave Airlie <airlied@linux.ie> | 2005-09-06 10:03:19 +0000 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2005-09-06 10:03:19 +0000 |
commit | cb63f8d9c0563fb0eff28e2be6d4adf5666540d2 (patch) | |
tree | e0fb9a3883bcc31d3888bdcd29d0e5d35033a57c | |
parent | dbd83cf18e1bf5e7e31e1ac150227bd27e8b1739 (diff) |
Handle VIP timeouts more gracefully -- impose a hard limit of 10ms on
waiting for VIP_BUSY so we don't lock up hard, spinning.
-rw-r--r-- | src/radeon_vip.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/src/radeon_vip.c b/src/radeon_vip.c index a75a89d..cc4b635 100644 --- a/src/radeon_vip.c +++ b/src/radeon_vip.c @@ -91,6 +91,18 @@ static CARD32 RADEONVIP_fifo_idle(GENERIC_BUS_Ptr b, CARD8 channel) ((device & 0x3)<<14) | (fifo << 12) | (addr) */ +#define VIP_WAIT_FOR_IDLE() { \ + int i2ctries = 0; \ + while (i2ctries < 10) { \ + status = RADEONVIP_idle(b); \ + if (status==VIP_BUSY) \ + { \ + usleep(1000); \ + i2ctries++; \ + } else break; \ + } \ + } + static Bool RADEONVIP_read(GENERIC_BUS_Ptr b, CARD32 address, CARD32 count, CARD8 *buffer) { ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; @@ -107,7 +119,7 @@ static Bool RADEONVIP_read(GENERIC_BUS_Ptr b, CARD32 address, CARD32 count, CARD RADEONWaitForFifo(pScrn, 2); OUTREG(RADEON_VIPH_REG_ADDR, address | 0x2000); write_mem_barrier(); - while(VIP_BUSY == (status = RADEONVIP_idle(b))); + VIP_WAIT_FOR_IDLE(); if(VIP_IDLE != status) return FALSE; /* @@ -126,7 +138,7 @@ static Bool RADEONVIP_read(GENERIC_BUS_Ptr b, CARD32 address, CARD32 count, CARD RADEONWaitForIdleMMIO(pScrn); INREG(RADEON_VIPH_REG_DATA); - while(VIP_BUSY == (status = RADEONVIP_idle(b))); + VIP_WAIT_FOR_IDLE(); if(VIP_IDLE != status) return FALSE; /* set RADEON_VIPH_REGR_DIS so that the read won't take too long. @@ -147,7 +159,7 @@ static Bool RADEONVIP_read(GENERIC_BUS_Ptr b, CARD32 address, CARD32 count, CARD *(CARD32 *)buffer=(CARD32) ( INREG(RADEON_VIPH_REG_DATA) & 0xffffffff); break; } - while(VIP_BUSY == (status = RADEONVIP_idle(b))); + VIP_WAIT_FOR_IDLE(); if(VIP_IDLE != status) return FALSE; /* so that reading RADEON_VIPH_REG_DATA would not trigger unnecessary vip cycles. |