summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>2006-09-15 11:18:35 +0200
committerThomas Hellstrom <thomas-at-tungstengraphics-dot-com>2006-09-15 11:18:35 +0200
commit49fbeb339c232804866cd548d6023fe559597353 (patch)
treefa4685050d7a91a7ee0e55f10093b4fa403a61aa /linux-core
parent7223b4e264a64df2df70715d8777f2ccaa883d5e (diff)
Some bugfixes.
Change the fence object interface somewhat to allow some more flexibility. Make list IOCTLS really restartable. Try to avoid busy-waits in the kernel using immediate return to user-space with an -EAGAIN.
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/drmP.h1
-rw-r--r--linux-core/drm_bo.c36
-rw-r--r--linux-core/drm_fence.c20
-rw-r--r--linux-core/i915_drv.c1
-rw-r--r--linux-core/i915_fence.c31
5 files changed, 58 insertions, 31 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 835b295a..d04a482b 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -655,6 +655,7 @@ typedef struct drm_ref_object {
typedef struct drm_bo_driver{
int cached_tt;
int cached_vram;
+ drm_local_map_t *vram_map;
drm_ttm_backend_t *(*create_ttm_backend_entry)
(struct drm_device *dev, int cached);
int (*fence_type)(uint32_t flags, uint32_t *class, uint32_t *type);
diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index f5a25c26..858a4cde 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -322,15 +322,15 @@ static int drm_bo_wait(drm_buffer_object_t * bo, int lazy, int ignore_signals,
bo->fence = NULL;
return 0;
}
- if (no_wait)
+ if (no_wait) {
return -EBUSY;
-
+ }
ret =
drm_fence_object_wait(dev, fence, lazy, ignore_signals,
bo->fence_flags);
- if (ret)
- return ret;
-
+ if (ret)
+ return ret;
+
drm_fence_usage_deref_unlocked(dev, fence);
bo->fence = NULL;
@@ -360,9 +360,14 @@ static int drm_bo_evict(drm_buffer_object_t * bo, int tt, int no_wait)
if (!tt && !bo->vram)
goto out;
+
ret = drm_bo_wait(bo, 0, 0, no_wait);
- if (ret)
+ if (ret) {
+ if (ret != -EAGAIN)
+ DRM_ERROR("Failed to expire fence before "
+ "buffer eviction.\n");
goto out;
+ }
if (tt) {
ret = drm_move_tt_to_local(bo);
@@ -420,7 +425,7 @@ int drm_bo_alloc_space(drm_buffer_object_t * buf, int tt, int no_wait)
} while (1);
if (!node) {
- DRM_ERROR("Out of aperture space\n");
+ DRM_ERROR("Out of videoram / aperture space\n");
mutex_unlock(&dev->struct_mutex);
return -ENOMEM;
}
@@ -646,7 +651,7 @@ static int drm_bo_busy(drm_buffer_object_t * bo)
bo->fence = NULL;
return 0;
}
- drm_fence_object_flush(dev, fence, DRM_FENCE_EXE);
+ drm_fence_object_flush(dev, fence, DRM_FENCE_TYPE_EXE);
if (drm_fence_object_signaled(fence, bo->fence_flags)) {
drm_fence_usage_deref_unlocked(dev, fence);
bo->fence = NULL;
@@ -981,11 +986,7 @@ static int drm_buffer_object_validate(drm_buffer_object_t * bo,
DRM_ERROR("Vram support not implemented yet\n");
return -EINVAL;
}
- if ((new_flags & (DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MEM_VRAM)) &&
- (new_flags & DRM_BO_FLAG_CACHED)) {
- DRM_ERROR("Cached binding not implemented yet\n");
- return -EINVAL;
- }
+
DRM_DEBUG("New flags 0x%08x, Old flags 0x%08x\n", new_flags, bo->flags);
ret = driver->fence_type(new_flags, &bo->fence_class, &bo->fence_flags);
if (ret) {
@@ -1003,8 +1004,11 @@ static int drm_buffer_object_validate(drm_buffer_object_t * bo,
return -EINVAL;
}
ret = drm_bo_move_buffer(bo, new_flags, no_wait);
- if (ret)
+ if (ret) {
+ if (ret != -EAGAIN)
+ DRM_ERROR("Failed moving buffer.\n");
return ret;
+ }
}
if (move_unfenced) {
@@ -1304,7 +1308,7 @@ int drm_bo_ioctl(DRM_IOCTL_ARGS)
DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg));
if (arg.handled) {
- data = req->next;
+ data = arg.next;
continue;
}
@@ -1404,7 +1408,7 @@ int drm_bo_ioctl(DRM_IOCTL_ARGS)
default:
rep.ret = -EINVAL;
}
- next = req->next;
+ next = arg.next;
/*
* A signal interrupted us. Make sure the ioctl is restartable.
diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c
index 9ade8114..5078e952 100644
--- a/linux-core/drm_fence.c
+++ b/linux-core/drm_fence.c
@@ -283,10 +283,10 @@ int drm_fence_object_flush(drm_device_t * dev,
write_lock_irqsave(&fm->lock, flags);
fence->flush_mask |= type;
if (fence->submitted_flush == fence->signaled) {
- if ((fence->type & DRM_FENCE_EXE) &&
- !(fence->submitted_flush & DRM_FENCE_EXE)) {
+ if ((fence->type & DRM_FENCE_TYPE_EXE) &&
+ !(fence->submitted_flush & DRM_FENCE_TYPE_EXE)) {
drm_fence_flush_exe(fm, driver, fence->sequence);
- fence->submitted_flush |= DRM_FENCE_EXE;
+ fence->submitted_flush |= DRM_FENCE_TYPE_EXE;
} else {
fm->pending_flush |= (fence->flush_mask &
~fence->submitted_flush);
@@ -362,7 +362,7 @@ int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence,
if (ret)
return ((ret == -EINTR) ? -EAGAIN : ret);
- } else if ((fence->class == 0) && (mask & DRM_FENCE_EXE) &&
+ } else if ((fence->class == 0) && (mask & DRM_FENCE_TYPE_EXE) &&
driver->lazy_capable) {
/*
@@ -372,7 +372,7 @@ int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence,
do {
DRM_WAIT_ON(ret, fm->fence_queue, 3 * DRM_HZ,
- fence_signaled(dev, fence, DRM_FENCE_EXE,
+ fence_signaled(dev, fence, DRM_FENCE_TYPE_EXE,
1));
if (time_after_eq(jiffies, _end))
break;
@@ -386,7 +386,15 @@ int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence,
if (fence_signaled(dev, fence, mask, 0))
return 0;
- do {
+ /*
+ * Avoid kernel-space busy-waits.
+ */
+#if 1
+ if (!ignore_signals)
+ return -EAGAIN;
+#endif
+ do {
+ schedule();
signaled = fence_signaled(dev, fence, mask, 1);
} while (!signaled && !time_after_eq(jiffies, _end));
diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c
index fb4754d8..1718bb31 100644
--- a/linux-core/i915_drv.c
+++ b/linux-core/i915_drv.c
@@ -49,6 +49,7 @@ static drm_fence_driver_t i915_fence_driver = {
};
static drm_bo_driver_t i915_bo_driver = {
+ .vram_map = NULL,
.cached_vram = 0,
.cached_tt = 1,
.create_ttm_backend_entry = i915_create_ttm_backend_entry,
diff --git a/linux-core/i915_fence.c b/linux-core/i915_fence.c
index 20e12d6a..5a8612cb 100644
--- a/linux-core/i915_fence.c
+++ b/linux-core/i915_fence.c
@@ -43,7 +43,6 @@ static void i915_perform_flush(drm_device_t * dev)
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
drm_fence_manager_t *fm = &dev->fm;
drm_fence_driver_t *driver = dev->driver->fence_driver;
- int flush_completed = 0;
uint32_t flush_flags = 0;
uint32_t flush_sequence = 0;
uint32_t i_status;
@@ -52,9 +51,14 @@ static void i915_perform_flush(drm_device_t * dev)
if (fm->pending_exe_flush) {
sequence = READ_BREADCRUMB(dev_priv);
+
+ /*
+ * First update fences with the current breadcrumb.
+ */
+
diff = sequence - fm->last_exe_flush;
if (diff < driver->wrap_diff && diff != 0) {
- drm_fence_handler(dev, sequence, DRM_FENCE_EXE);
+ drm_fence_handler(dev, sequence, DRM_FENCE_TYPE_EXE);
}
diff = sequence - fm->exe_flush_sequence;
@@ -69,20 +73,18 @@ static void i915_perform_flush(drm_device_t * dev)
dev_priv->fence_irq_on = 1;
}
}
+
if (dev_priv->flush_pending) {
i_status = READ_HWSP(dev_priv, 0);
if ((i_status & (1 << 12)) !=
(dev_priv->saved_flush_status & (1 << 12))) {
- flush_completed = 1;
flush_flags = dev_priv->flush_flags;
flush_sequence = dev_priv->flush_sequence;
dev_priv->flush_pending = 0;
- } else {
- }
- }
- if (flush_completed) {
- drm_fence_handler(dev, flush_sequence, flush_flags);
+ drm_fence_handler(dev, flush_sequence, flush_flags);
+ }
}
+
if (fm->pending_flush && !dev_priv->flush_pending) {
dev_priv->flush_sequence = (uint32_t) READ_BREADCRUMB(dev_priv);
dev_priv->flush_flags = fm->pending_flush;
@@ -91,6 +93,18 @@ static void i915_perform_flush(drm_device_t * dev)
dev_priv->flush_pending = 1;
fm->pending_flush = 0;
}
+
+ if (dev_priv->flush_pending) {
+ i_status = READ_HWSP(dev_priv, 0);
+ if ((i_status & (1 << 12)) !=
+ (dev_priv->saved_flush_status & (1 << 12))) {
+ flush_flags = dev_priv->flush_flags;
+ flush_sequence = dev_priv->flush_sequence;
+ dev_priv->flush_pending = 0;
+ drm_fence_handler(dev, flush_sequence, flush_flags);
+ }
+ }
+
}
void i915_poke_flush(drm_device_t * dev)
@@ -117,7 +131,6 @@ void i915_fence_handler(drm_device_t * dev)
write_lock(&fm->lock);
i915_perform_flush(dev);
- i915_perform_flush(dev);
write_unlock(&fm->lock);
}