57,7 → 57,6 |
radeon_fence_ring_emit(rdev, fence); |
|
fence->emited = true; |
fence->timeout = jiffies + ((2000 * HZ) / 1000); |
list_del(&fence->list); |
list_add_tail(&fence->list, &rdev->fence_drv.emited); |
write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); |
70,15 → 69,42 |
struct list_head *i, *n; |
uint32_t seq; |
bool wake = false; |
unsigned long cjiffies; |
|
if (rdev == NULL) { |
return true; |
if (rdev->wb.enabled) { |
u32 scratch_index; |
if (rdev->wb.use_event) |
scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; |
else |
scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; |
seq = rdev->wb.wb[scratch_index/4]; |
} else |
seq = RREG32(rdev->fence_drv.scratch_reg); |
if (seq != rdev->fence_drv.last_seq) { |
rdev->fence_drv.last_seq = seq; |
rdev->fence_drv.last_jiffies = jiffies; |
rdev->fence_drv.last_timeout = RADEON_FENCE_JIFFIES_TIMEOUT; |
} else { |
cjiffies = jiffies; |
if (time_after(cjiffies, rdev->fence_drv.last_jiffies)) { |
cjiffies -= rdev->fence_drv.last_jiffies; |
if (time_after(rdev->fence_drv.last_timeout, cjiffies)) { |
/* update the timeout */ |
rdev->fence_drv.last_timeout -= cjiffies; |
} else { |
/* the 500ms timeout is elapsed we should test |
* for GPU lockup |
*/ |
rdev->fence_drv.last_timeout = 1; |
} |
if (rdev->shutdown) { |
return true; |
} else { |
/* wrap around update last jiffies, we will just wait |
* a little longer |
*/ |
rdev->fence_drv.last_jiffies = cjiffies; |
} |
seq = RREG32(rdev->fence_drv.scratch_reg); |
rdev->fence_drv.last_seq = seq; |
return false; |
} |
n = NULL; |
list_for_each(i, &rdev->fence_drv.emited) { |
fence = list_entry(i, struct radeon_fence, list); |
170,9 → 196,8 |
int radeon_fence_wait(struct radeon_fence *fence, bool intr) |
{ |
struct radeon_device *rdev; |
unsigned long cur_jiffies; |
unsigned long timeout; |
bool expired = false; |
unsigned long irq_flags, timeout; |
u32 seq; |
int r; |
|
if (fence == NULL) { |
183,21 → 208,18 |
if (radeon_fence_signaled(fence)) { |
return 0; |
} |
|
timeout = rdev->fence_drv.last_timeout; |
retry: |
cur_jiffies = jiffies; |
timeout = HZ / 100; |
if (time_after(fence->timeout, cur_jiffies)) { |
timeout = fence->timeout - cur_jiffies; |
} |
|
/* save current sequence used to check for GPU lockup */ |
seq = rdev->fence_drv.last_seq; |
if (intr) { |
radeon_irq_kms_sw_irq_get(rdev); |
r = wait_event_interruptible_timeout(rdev->fence_drv.queue, |
radeon_fence_signaled(fence), timeout); |
radeon_irq_kms_sw_irq_put(rdev); |
if (unlikely(r < 0)) |
if (unlikely(r < 0)) { |
return r; |
} |
} else { |
radeon_irq_kms_sw_irq_get(rdev); |
r = wait_event_timeout(rdev->fence_drv.queue, |
205,38 → 227,37 |
radeon_irq_kms_sw_irq_put(rdev); |
} |
if (unlikely(!radeon_fence_signaled(fence))) { |
if (unlikely(r == 0)) { |
expired = true; |
/* we were interrupted for some reason and fence isn't |
* isn't signaled yet, resume wait |
*/ |
if (r) { |
timeout = r; |
goto retry; |
} |
if (unlikely(expired)) { |
timeout = 1; |
if (time_after(cur_jiffies, fence->timeout)) { |
timeout = cur_jiffies - fence->timeout; |
} |
timeout = jiffies_to_msecs(timeout); |
if (timeout > 500) { |
DRM_ERROR("fence(%p:0x%08X) %lums timeout " |
"going to reset GPU\n", |
fence, fence->seq, timeout); |
radeon_gpu_reset(rdev); |
/* don't protect read access to rdev->fence_drv.last_seq |
* if we experiencing a lockup the value doesn't change |
*/ |
if (seq == rdev->fence_drv.last_seq && radeon_gpu_is_lockup(rdev)) { |
/* good news we believe it's a lockup */ |
WARN(1, "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n", |
fence->seq, seq); |
/* FIXME: what should we do ? marking everyone |
* as signaled for now |
*/ |
rdev->gpu_lockup = true; |
r = radeon_gpu_reset(rdev); |
if (r) |
return r; |
WREG32(rdev->fence_drv.scratch_reg, fence->seq); |
rdev->gpu_lockup = false; |
} |
} |
timeout = RADEON_FENCE_JIFFIES_TIMEOUT; |
write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); |
rdev->fence_drv.last_timeout = RADEON_FENCE_JIFFIES_TIMEOUT; |
rdev->fence_drv.last_jiffies = jiffies; |
write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); |
goto retry; |
} |
if (unlikely(expired)) { |
rdev->fence_drv.count_timeout++; |
cur_jiffies = jiffies; |
timeout = 1; |
if (time_after(cur_jiffies, fence->timeout)) { |
timeout = cur_jiffies - fence->timeout; |
} |
timeout = jiffies_to_msecs(timeout); |
DRM_ERROR("fence(%p:0x%08X) %lums timeout\n", |
fence, fence->seq, timeout); |
DRM_ERROR("last signaled fence(0x%08X)\n", |
rdev->fence_drv.last_seq); |
} |
return 0; |
} |
|
332,7 → 353,6 |
INIT_LIST_HEAD(&rdev->fence_drv.created); |
INIT_LIST_HEAD(&rdev->fence_drv.emited); |
INIT_LIST_HEAD(&rdev->fence_drv.signaled); |
rdev->fence_drv.count_timeout = 0; |
init_waitqueue_head(&rdev->fence_drv.queue); |
rdev->fence_drv.initialized = true; |
write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); |