added timeout and abort for DMA idle waits. This keeps the system responsive if the DMA engine fails, which is way better than a complete hang. Adding this because it's not impossible to create a situation that stalls DMA: for instance if a video app writes (way) outside it's allocated overlay buffers.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10976 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -32,17 +32,35 @@ static void nv_start_dma(void);
|
|||||||
static status_t nv_acc_fifofree_dma(uint16 cmd_size);
|
static status_t nv_acc_fifofree_dma(uint16 cmd_size);
|
||||||
static void nv_acc_cmd_dma(uint32 cmd, uint16 offset, uint16 size);
|
static void nv_acc_cmd_dma(uint32 cmd, uint16 offset, uint16 size);
|
||||||
|
|
||||||
|
/* used to track engine DMA stalls */
|
||||||
|
static uint8 err;
|
||||||
|
|
||||||
|
/* wait until engine completely idle */
|
||||||
status_t nv_acc_wait_idle_dma()
|
status_t nv_acc_wait_idle_dma()
|
||||||
{
|
{
|
||||||
/* wait until engine completely idle */
|
/* we'd better check for timeouts on the DMA engine as it's theoretically
|
||||||
|
* breakable by malfunctioning software */
|
||||||
|
uint16 cnt = 0;
|
||||||
|
|
||||||
/* wait until all upcoming commands are in execution at least */
|
/* wait until all upcoming commands are in execution at least. Do this until
|
||||||
while (NV_REG32(NVACC_FIFO + NV_GENERAL_DMAGET +
|
* we hit a timeout; abort if we failed at least three times before:
|
||||||
|
* if DMA stalls, we have to forget about it alltogether at some point, or
|
||||||
|
* the system will almost come to a complete halt.. */
|
||||||
|
while ((NV_REG32(NVACC_FIFO + NV_GENERAL_DMAGET +
|
||||||
si->engine.fifo.handle[(si->engine.fifo.ch_ptr[NV_ROP5_SOLID])])
|
si->engine.fifo.handle[(si->engine.fifo.ch_ptr[NV_ROP5_SOLID])])
|
||||||
!= (si->engine.dma.put << 2))
|
!= (si->engine.dma.put << 2)) &&
|
||||||
|
(cnt < 10000) && (err < 3))
|
||||||
{
|
{
|
||||||
/* snooze a bit so I do not hammer the bus */
|
/* snooze a bit so I do not hammer the bus */
|
||||||
snooze (100);
|
snooze (100);
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* log timeout if we had one */
|
||||||
|
if (cnt == 10000)
|
||||||
|
{
|
||||||
|
err++;
|
||||||
|
LOG(4,("ACC_DMA: wait_idle DMA timeout #%d, engine trouble!\n", err));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wait until execution completed */
|
/* wait until execution completed */
|
||||||
@@ -61,6 +79,8 @@ status_t nv_acc_init_dma()
|
|||||||
{
|
{
|
||||||
uint16 cnt;
|
uint16 cnt;
|
||||||
uint32 surf_depth, patt_depth;
|
uint32 surf_depth, patt_depth;
|
||||||
|
/* reset the engine DMA stalls counter */
|
||||||
|
err = 0;
|
||||||
|
|
||||||
/* a hanging engine only recovers from a complete power-down/power-up cycle */
|
/* a hanging engine only recovers from a complete power-down/power-up cycle */
|
||||||
NV_REG32(NV32_PWRUPCTRL) = 0x13110011;
|
NV_REG32(NV32_PWRUPCTRL) = 0x13110011;
|
||||||
@@ -755,7 +775,7 @@ status_t nv_acc_init_dma()
|
|||||||
patt_depth = 0x00000003;
|
patt_depth = 0x00000003;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(8,("ACC: init, invalid bit depth\n"));
|
LOG(8,("ACC_DMA: init, invalid bit depth\n"));
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user