diff options
author | Thomas Hellstrom <thomas@tungstengraphics.com> | 2006-03-17 16:48:22 +0000 |
---|---|---|
committer | Thomas Hellstrom <thomas@tungstengraphics.com> | 2006-03-17 16:48:22 +0000 |
commit | 364321f166c58a81e75563a39272b97aef1469aa (patch) | |
tree | a282a63f5b7bf8ba462d4013d04544e04fd9ae82 | |
parent | 6329fc3733e72690160cbfa2e317deeef85adb1c (diff) |
Handle signals correctly while waiting for fence.
-rw-r--r-- | libdrm/xf86mm.c | 15 | ||||
-rw-r--r-- | linux-core/drm_ttm.c | 66 | ||||
-rw-r--r-- | shared-core/i915_irq.c | 9 |
3 files changed, 57 insertions, 33 deletions
diff --git a/libdrm/xf86mm.c b/libdrm/xf86mm.c index b25bcc85..ec0cc682 100644 --- a/libdrm/xf86mm.c +++ b/libdrm/xf86mm.c @@ -249,6 +249,7 @@ drmWaitFence(int drmFD, drmFence fence) { drm_fence_arg_t arg; int retired; + int ret; drmMMCheckInit(drmFD); @@ -268,13 +269,16 @@ drmWaitFence(int drmFD, drmFence fence) fence.fenceSeq) < DRM_MM_WRAP) return 0; #endif - arg.req.op = wait_fence; - arg.req.fence_type = fence.fenceType; - arg.req.fence_seq = fence.fenceSeq; - if (ioctl(drmFD, DRM_IOCTL_FENCE, &arg)) { - drmMsg("drmWaitFence: failed: %s\n", strerror(errno)); + do { + arg.req.op = wait_fence; + arg.req.fence_type = fence.fenceType; + arg.req.fence_seq = fence.fenceSeq; + ret = ioctl(drmFD, DRM_IOCTL_FENCE, &arg); + } while (ret == -EAGAIN); + if (ret) { + drmMsg("drmWaitFence: failed: %s\n", strerror(errno)); return -errno; } @@ -888,7 +892,6 @@ drmMMValidateBuffers(int drmFD, drmMMBufList * head) buf->err = curBArg->ret; if (buf->err) { ret = buf->err; - abort(); } block->kernelBuf = curBArg->region_handle; block->hasKernelBuf = 1; diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index 666ac511..41d23112 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -406,6 +406,35 @@ static int drm_set_caching(drm_ttm_t * ttm, unsigned long page_offset, } /* + * Wait for a maximum of one second for a buffer to become free. + * Note that we block completely in a buzy wait loop here + * if a signal is pending. Could be made to behave more nicely. + */ + +static int drm_wait_buf_busy(drm_ttm_backend_list_t * entry) +{ + drm_mm_node_t *mm_node = entry->mm_node; + drm_device_t *dev = entry->mm->dev; + drm_ttm_mm_priv_t *mm_priv; + unsigned long end = jiffies + DRM_HZ; + int ret = 0; + + if (!mm_node) + return 0; + + mm_priv = (drm_ttm_mm_priv_t *) mm_node->private; + if (mm_priv->fence_valid) { + do { + ret = dev->mm_driver->wait_fence(dev, entry->fence_type, + mm_priv->fence); + if (time_after_eq(jiffies, end)) + ret = -EBUSY; + } while (ret == -EAGAIN); + } + return ret; +} + +/* * Take a ttm region out of the aperture manager. */ @@ -421,8 +450,8 @@ static int remove_ttm_region(drm_ttm_backend_list_t * entry, int ret_if_busy) if (!mm_node) return 0; - entry->mm_node = NULL; mm_priv = (drm_ttm_mm_priv_t *) mm_node->private; + if (!mm_priv) return 0; @@ -431,12 +460,12 @@ static int remove_ttm_region(drm_ttm_backend_list_t * entry, int ret_if_busy) && !dev->mm_driver->test_fence(mm->dev, entry->fence_type, mm_priv->fence)) return -EBUSY; - ret = dev->mm_driver->wait_fence(mm->dev, entry->fence_type, - mm_priv->fence); + ret = drm_wait_buf_busy(entry); if (ret) return ret; } + entry->mm_node = NULL; mm_node->private = NULL; spin_lock(&mm->mm.mm_lock); list_del(&mm_priv->lru); @@ -914,6 +943,7 @@ static int drm_ttm_evict_lru_sl(drm_ttm_backend_list_t * entry) uint32_t evict_fence; drm_device_t *dev = mm->dev; drm_mm_node_t *evict_node; + int ret; /* * We must use a loop here, since the list might be updated while we release @@ -942,11 +972,17 @@ static int drm_ttm_evict_lru_sl(drm_ttm_backend_list_t * entry) spin_unlock(mm_lock); up(&dev->struct_sem); - dev->mm_driver->wait_fence(dev, evict_priv->region->fence_type, - evict_fence); + + ret = drm_wait_buf_busy(evict_priv->region); + down(&dev->struct_sem); spin_lock(mm_lock); + if (ret) { + DRM_ERROR("Evict wait timed out\n"); + return ret; + } + } while (TRUE); evict_node = evict_priv->region->mm_node; @@ -975,26 +1011,6 @@ typedef struct drm_val_action { int validated; } drm_val_action_t; -static int drm_wait_buf_busy(drm_ttm_backend_list_t * entry) -{ - drm_mm_node_t *mm_node = entry->mm_node; - drm_device_t *dev = entry->mm->dev; - drm_ttm_mm_priv_t *mm_priv; - int ret = 0; - - if (!mm_node) - return 0; - - mm_priv = (drm_ttm_mm_priv_t *) mm_node->private; - if (mm_priv->fence_valid) { - do { - ret = dev->mm_driver->wait_fence(dev, entry->fence_type, - mm_priv->fence); - } while (ret == -EINTR); - } - return ret; -} - static int drm_validate_ttm_region(drm_ttm_backend_list_t * entry, unsigned *aper_offset, drm_val_action_t * action, diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 30525583..b49bbd76 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -285,10 +285,15 @@ int i915_wait_fence(drm_device_t * dev, uint32_t type, uint32_t fence) } while (ret == 0); } - if (ret && ret != -EINTR) { + if (ret && ret != DRM_ERR(EINTR)) { DRM_ERROR("Fence timeout %d %d\n", READ_BREADCRUMB(dev_priv), fence); } + dev->mm_driver->mm_sarea->retired[0] = READ_BREADCRUMB(dev_priv); - return ret; + + if (ret == DRM_ERR(EINTR)) + return DRM_ERR(EAGAIN); + else + return ret; } |