summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thomas@tungstengraphics.com>2006-03-17 16:48:22 +0000
committerThomas Hellstrom <thomas@tungstengraphics.com>2006-03-17 16:48:22 +0000
commit364321f166c58a81e75563a39272b97aef1469aa (patch)
treea282a63f5b7bf8ba462d4013d04544e04fd9ae82
parent6329fc3733e72690160cbfa2e317deeef85adb1c (diff)
Handle signals correctly while waiting for fence.
-rw-r--r--libdrm/xf86mm.c15
-rw-r--r--linux-core/drm_ttm.c66
-rw-r--r--shared-core/i915_irq.c9
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;
}