summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thomas@tungstengraphics.com>2006-02-28 23:48:34 +0000
committerThomas Hellstrom <thomas@tungstengraphics.com>2006-02-28 23:48:34 +0000
commit71c507586709e12142dad95d7a56b026c4448f84 (patch)
tree00936d3d42c901435dc15e8df2beda061c1c63ef
parent2639c7af46c15ca08a9504ac0915d70bb3dcfe9a (diff)
mm: Kernel side of fence IOCTL. Fence code updated to know about fence
types. Current intel code has just one type of fences.
-rw-r--r--linux-core/drmP.h9
-rw-r--r--linux-core/drm_fops.c18
-rw-r--r--linux-core/drm_ttm.c106
-rw-r--r--linux-core/drm_ttm.h1
-rw-r--r--linux-core/i915_ttm.c1
-rw-r--r--shared-core/drm.h39
-rw-r--r--shared-core/i915_drv.h6
-rw-r--r--shared-core/i915_irq.c54
8 files changed, 178 insertions, 56 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 6c351f0a..e8c02861 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -585,6 +585,7 @@ typedef struct drm_ttm_mm {
} drm_ttm_mm_t;
typedef struct drm_mm_driver {
+ int fence_types;
int evicted_vram;
int evicted_tt;
int validated;
@@ -593,9 +594,11 @@ typedef struct drm_mm_driver {
drm_mm_t vr_mm;
drm_map_list_t *mm_sarea_map;
volatile drm_mm_sarea_t *mm_sarea;
- uint32_t(*emit_fence) (struct drm_device * dev);
- int (*wait_fence) (struct drm_device * dev, uint32_t fence);
- int (*test_fence) (struct drm_device * dev, uint32_t fence);
+ uint32_t(*emit_fence) (struct drm_device * dev, uint32_t type);
+ int (*wait_fence) (struct drm_device * dev, uint32_t type,
+ uint32_t fence);
+ int (*test_fence) (struct drm_device * dev, uint32_t type,
+ uint32_t fence);
void (*flush_caches) (struct drm_device * dev, int access);
drm_ttm_backend_t *(*create_ttm_backend_entry) (struct drm_device * dev,
int cached);
diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c
index 800316a7..01b32055 100644
--- a/linux-core/drm_fops.c
+++ b/linux-core/drm_fops.c
@@ -362,9 +362,13 @@ int drm_release(struct inode *inode, struct file *filp)
if (dev->driver->reclaim_buffers_locked)
dev->driver->reclaim_buffers_locked(dev, filp);
+ /*
+ * FIXME: These need to go away.
+ */
+
if (dev->mm_driver) {
- uint32_t fence = dev->mm_driver->emit_fence(dev);
- dev->mm_driver->wait_fence(dev, fence);
+ uint32_t fence = dev->mm_driver->emit_fence(dev, 0);
+ dev->mm_driver->wait_fence(dev, 0, fence);
}
drm_lock_free(dev, &dev->lock.hw_lock->lock,
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
@@ -406,9 +410,15 @@ int drm_release(struct inode *inode, struct file *filp)
if (!retcode) {
if (dev->driver->reclaim_buffers_locked)
dev->driver->reclaim_buffers_locked(dev, filp);
+
+ /*
+ * FIXME: These need to go away.
+ */
+
+
if (dev->mm_driver) {
- uint32_t fence = dev->mm_driver->emit_fence(dev);
- dev->mm_driver->wait_fence(dev, fence);
+ uint32_t fence = dev->mm_driver->emit_fence(dev, 0);
+ dev->mm_driver->wait_fence(dev, 0, fence);
}
drm_lock_free(dev, &dev->lock.hw_lock->lock,
diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c
index 78b28ca3..be137406 100644
--- a/linux-core/drm_ttm.c
+++ b/linux-core/drm_ttm.c
@@ -391,7 +391,8 @@ static void remove_ttm_region(drm_ttm_backend_list_t * entry)
return;
if (mm_priv->fence_valid)
- dev->mm_driver->wait_fence(mm->dev, mm_priv->fence);
+ dev->mm_driver->wait_fence(mm->dev, entry->fence_type,
+ mm_priv->fence);
mm_node->private = NULL;
spin_lock(&mm->mm.mm_lock);
list_del(&mm_priv->lru);
@@ -763,10 +764,15 @@ int drm_add_ttm(drm_device_t * dev, unsigned size, drm_map_list_t ** maplist)
* Fence all unfenced regions in the global lru list.
*/
-static void drm_ttm_fence_regions(drm_ttm_mm_t * mm, uint32_t fence)
+static void drm_ttm_fence_regions(drm_device_t * dev, drm_ttm_mm_t * mm)
{
+ int emitted[DRM_FENCE_TYPES];
+ uint32_t fence_seqs[DRM_FENCE_TYPES];
struct list_head *list;
+ uint32_t fence_type;
+ uint32_t fence;
+ memset(emitted, 0, sizeof(int) * DRM_FENCE_TYPES);
spin_lock(&mm->mm.mm_lock);
list_for_each_prev(list, &mm->lru_head) {
@@ -774,6 +780,17 @@ static void drm_ttm_fence_regions(drm_ttm_mm_t * mm, uint32_t fence)
list_entry(list, drm_ttm_mm_priv_t, lru);
if (entry->fence_valid)
break;
+
+ fence_type = entry->region->fence_type;
+
+ if (!emitted[fence_type]) {
+ fence = dev->mm_driver->emit_fence(dev, fence_type);
+ fence_seqs[fence_type] = fence;
+ emitted[fence_type] = TRUE;
+ } else {
+ fence = fence_seqs[fence_type];
+ }
+
entry->fence = fence;
entry->fence_valid = TRUE;
}
@@ -789,8 +806,7 @@ static void drm_ttm_fence_regions(drm_ttm_mm_t * mm, uint32_t fence)
* May sleep while waiting for a fence.
*/
-static int drm_ttm_evict_lru_sl(drm_ttm_backend_list_t * entry,
- int *have_fence, uint32_t * cur_fence)
+static int drm_ttm_evict_lru_sl(drm_ttm_backend_list_t * entry)
{
struct list_head *list;
drm_ttm_mm_t *mm = entry->mm;
@@ -815,16 +831,16 @@ static int drm_ttm_evict_lru_sl(drm_ttm_backend_list_t * entry,
}
evict_fence = evict_priv->fence;
- if (*have_fence && ((*cur_fence - evict_fence) < (1 << 23)))
- break;
+
spin_unlock(mm_lock);
up(&dev->struct_sem);
- dev->mm_driver->wait_fence(dev, evict_fence);
+ dev->mm_driver->wait_fence(dev, evict_priv->region->fence_type,
+ evict_fence);
down(&dev->struct_sem);
spin_lock(mm_lock);
- *cur_fence = evict_fence;
- *have_fence = TRUE;
+
} while (TRUE);
+
DRM_ERROR("Evicting 0x%lx\n", (unsigned long)evict_priv->region);
dev->mm_driver->evicted_tt = TRUE;
evict_node = evict_priv->region->mm_node;
@@ -834,6 +850,7 @@ static int drm_ttm_evict_lru_sl(drm_ttm_backend_list_t * entry,
drm_mm_put_block_locked(&mm->mm, evict_node);
evict_priv->region->mm_node = NULL;
drm_free(evict_priv, sizeof(*evict_priv), DRM_MEM_MM);
+
return 0;
}
@@ -846,13 +863,11 @@ static int drm_ttm_evict_lru_sl(drm_ttm_backend_list_t * entry,
*/
static int drm_validate_ttm_region(drm_ttm_backend_list_t * entry,
- unsigned *aper_offset)
+ uint32_t fence_type, unsigned *aper_offset)
{
drm_mm_node_t *mm_node = entry->mm_node;
drm_ttm_mm_t *mm = entry->mm;
spinlock_t *mm_lock = &mm->mm.mm_lock;
- uint32_t cur_fence = 0;
- int have_fence = FALSE;
drm_ttm_mm_priv_t *mm_priv;
unsigned num_pages;
int ret;
@@ -872,9 +887,7 @@ static int drm_validate_ttm_region(drm_ttm_backend_list_t * entry,
mm_node =
drm_mm_search_free_locked(&entry->mm->mm, num_pages, 0, 0);
if (!mm_node) {
- ret =
- drm_ttm_evict_lru_sl(entry, &have_fence,
- &cur_fence);
+ ret = drm_ttm_evict_lru_sl(entry);
if (ret) {
spin_unlock(mm_lock);
return ret;
@@ -892,6 +905,8 @@ static int drm_validate_ttm_region(drm_ttm_backend_list_t * entry,
}
mm_priv->fence_valid = FALSE;
+ entry->fence_type = fence_type;
+
if (!entry->pinned)
list_add_tail(&mm_priv->lru, &mm->lru_head);
@@ -1065,8 +1080,13 @@ static void drm_ttm_handle_buf(drm_file_t * priv, drm_ttm_buf_arg_t * buf_p)
if (buf_p->ret)
break;
ttm_mm = entry->mm;
+ if (buf_p->fence_type >= dev->mm_driver->fence_types) {
+ buf_p->ret = -EINVAL;
+ break;
+ }
buf_p->ret =
- drm_validate_ttm_region(entry, &buf_p->aper_offset);
+ drm_validate_ttm_region(entry, buf_p->fence_type,
+ &buf_p->aper_offset);
break;
case ttm_validate:
buf_p->ret =
@@ -1087,8 +1107,13 @@ static void drm_ttm_handle_buf(drm_file_t * priv, drm_ttm_buf_arg_t * buf_p)
break;
}
ttm_mm = entry->mm;
+ if (buf_p->fence_type >= dev->mm_driver->fence_types) {
+ buf_p->ret = -EINVAL;
+ break;
+ }
buf_p->ret =
- drm_validate_ttm_region(entry, &buf_p->aper_offset);
+ drm_validate_ttm_region(entry, buf_p->fence_type,
+ &buf_p->aper_offset);
break;
case ttm_unbind:
buf_p->ret =
@@ -1182,8 +1207,7 @@ int drm_ttm_handle_bufs(drm_file_t * priv, drm_ttm_arg_t * ttm_arg)
if (ttm_arg->do_fence) {
if (old_priv != priv)
DRM_ERROR("Fence was from wrong client\n");
- drm_ttm_fence_regions(&mm_driver->ttm_mm,
- mm_driver->emit_fence(dev));
+ drm_ttm_fence_regions(dev, &mm_driver->ttm_mm);
}
for (i = 0; i < ttm_arg->num_bufs; ++i) {
@@ -1378,7 +1402,7 @@ int drm_mm_do_init(drm_device_t * dev, drm_mm_init_arg_t * arg)
_DRM_SHM, 0, &mm_sarea);
if (ret) {
dev->mm_driver->takedown(dev->mm_driver);
- DRM_ERROR("Failed to add a Memory manager SAREA.\n");
+ DRM_ERROR("Failed to add a memory manager SAREA.\n");
return -ENOMEM;
}
@@ -1431,3 +1455,45 @@ int drm_mm_init_ioctl(DRM_IOCTL_ARGS)
}
EXPORT_SYMBOL(drm_mm_init_ioctl);
+
+int drm_mm_fence_ioctl(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+
+ int ret;
+ drm_fence_arg_t arg;
+ drm_mm_driver_t *mm_driver = dev->mm_driver;
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+ if (!mm_driver) {
+ DRM_ERROR("Memory manager is not initialized.\n");
+ return -EINVAL;
+ }
+
+ DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg));
+
+ ret = 0;
+ switch (arg.op) {
+ case emit_fence:
+ arg.fence_seq = mm_driver->emit_fence(dev, arg.fence_type);
+ break;
+ case wait_fence:
+ arg.ret = mm_driver->wait_fence(dev, arg.fence_type,
+ arg.fence_seq);
+ break;
+ case test_fence:
+ arg.ret = mm_driver->test_fence(dev, arg.fence_type,
+ arg.fence_seq);
+ break;
+ default:
+ DRM_ERROR("Unsupported memory manager operation.\n");
+ ret = -EINVAL;
+ }
+
+ if (ret)
+ return ret;
+
+ DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg));
+
+ return 0;
+}
diff --git a/linux-core/drm_ttm.h b/linux-core/drm_ttm.h
index 77f11bf0..49c6121d 100644
--- a/linux-core/drm_ttm.h
+++ b/linux-core/drm_ttm.h
@@ -39,6 +39,7 @@ typedef struct drm_ttm_backend_list {
struct page **anon_pages;
int anon_locked;
int pinned;
+ uint32_t fence_type;
struct drm_mm_node *mm_node;
struct drm_ttm_mm *mm;
enum {
diff --git a/linux-core/i915_ttm.c b/linux-core/i915_ttm.c
index 9e6190ba..6469a984 100644
--- a/linux-core/i915_ttm.c
+++ b/linux-core/i915_ttm.c
@@ -23,6 +23,7 @@ drm_mm_driver_t *i915_mm_init(drm_device_t * dev)
{
drm_mm_driver_t *mm_driver =
drm_calloc(1, sizeof(*mm_driver), DRM_MEM_MM);
+ mm_driver->fence_types = 1;
mm_driver->emit_fence = i915_emit_fence;
mm_driver->wait_fence = i915_wait_fence;
mm_driver->test_fence = i915_test_fence;
diff --git a/shared-core/drm.h b/shared-core/drm.h
index e0e25769..a094836a 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -658,6 +658,7 @@ typedef struct drm_ttm_buf_arg {
char __user *user_addr;
unsigned long user_size;
struct drm_ttm_buf_arg __user *next;
+ unsigned fence_type;
int ret;
} drm_ttm_buf_arg_t;
@@ -680,22 +681,40 @@ typedef struct drm_mm_init_arg {
mm_init,
mm_takedown
} op;
- uint32_t vr_offset_lo;
- uint32_t vr_offset_hi;
- uint32_t vr_size_lo;
- uint32_t vr_size_hi;
- uint32_t tt_p_offset_lo;
- uint32_t tt_p_offset_hi;
- uint32_t tt_p_size_lo;
- uint32_t tt_p_size_hi;
+ unsigned vr_offset_lo;
+ unsigned vr_offset_hi;
+ unsigned vr_size_lo;
+ unsigned vr_size_hi;
+ unsigned tt_p_offset_lo;
+ unsigned tt_p_offset_hi;
+ unsigned tt_p_size_lo;
+ unsigned tt_p_size_hi;
drm_handle_t mm_sarea;
} drm_mm_init_arg_t;
+typedef struct drm_fence_arg {
+ enum {
+ emit_fence,
+ wait_fence,
+ test_fence
+ } op;
+ unsigned fence_seq;
+ unsigned fence_type;
+ int ret;
+} drm_fence_arg_t ;
+
#define DRM_MM_SAREA_SIZE 4096
+/*
+ * Different fence types for different part of chip and function. For example
+ * 3D / 2D, SG blitter, mc, video scaler * rwx etc. Up to driver to define.
+ */
+
+#define DRM_FENCE_TYPES 128
+
typedef struct drm_mm_sarea{
- unsigned emitted[32]; /* Last emitted fence */
- unsigned retired[32]; /* Last retired fence */
+ unsigned emitted[DRM_FENCE_TYPES]; /* Last emitted fence */
+ unsigned retired[DRM_FENCE_TYPES]; /* Last retired fence */
unsigned validation_seq; /* Seq. no of last validation call */
unsigned evict_vram_seq; /* Seq. no of last call vram was evicted */
unsigned evict_tt_seq; /* Seq. no of last call agp pages were evicted */
diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h
index 19b256b2..5ec5a5d7 100644
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@ -121,9 +121,9 @@ extern void i915_driver_irq_preinstall(drm_device_t * dev);
extern void i915_driver_irq_postinstall(drm_device_t * dev);
extern void i915_driver_irq_uninstall(drm_device_t * dev);
-extern uint32_t i915_emit_fence(drm_device_t * dev);
-extern int i915_wait_fence(drm_device_t * dev, uint32_t fence);
-extern int i915_test_fence(drm_device_t * dev, uint32_t fence);
+extern uint32_t i915_emit_fence(drm_device_t * dev, uint32_t type);
+extern int i915_wait_fence(drm_device_t * dev, uint32_t type, uint32_t fence);
+extern int i915_test_fence(drm_device_t * dev, uint32_t type, uint32_t fence);
/* i915_mem.c */
diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c
index b273c041..93c4c79d 100644
--- a/shared-core/i915_irq.c
+++ b/shared-core/i915_irq.c
@@ -210,23 +210,18 @@ void i915_driver_irq_uninstall(drm_device_t * dev)
I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
}
-uint32_t i915_emit_fence(drm_device_t * dev)
+uint32_t i915_emit_fence(drm_device_t * dev, uint32_t type)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
if (!dev_priv)
return 0;
-/*
- * FIXME: Disable for now since we're using
- */
-#if 0
- i915_emit_mi_flush(dev, MI_READ_FLUSH | MI_EXE_FLUSH);
-#endif
+ dev->mm_driver->mm_sarea->emitted[0] = dev_priv->counter;
return dev_priv->counter;
}
-int i915_test_fence(drm_device_t * dev, uint32_t fence)
+static int i915_do_test_fence(drm_device_t * dev, uint32_t fence)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -239,7 +234,7 @@ int i915_test_fence(drm_device_t * dev, uint32_t fence)
return (test < (1 << 23));
}
-int i915_sync_flush(drm_device_t *dev)
+static int i915_sync_flush(drm_device_t *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
uint32_t saved_status, i_status;
@@ -252,29 +247,56 @@ int i915_sync_flush(drm_device_t *dev)
if ((i_status & ( 1 << 12)) != (saved_status & (1 << 12)))
return 0;
}
- DRM_ERROR("Sync Flush timeout: HWSP: 0x%x, 0x%x %d\n", saved_status, i_status, i);
+ DRM_ERROR("Sync Flush timeout: HWSP: 0x%x, 0x%x %d\n",
+ saved_status, i_status, i);
return 1;
}
+
+int i915_test_fence(drm_device_t *dev, uint32_t type, uint32_t fence)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ int tmp = i915_do_test_fence(dev, fence);
+
+ fence = READ_BREADCRUMB(dev_priv);
+
+ i915_sync_flush(dev);
+
+ dev->mm_driver->mm_sarea->retired[0] = fence;
+
+ return tmp;
+}
+
/*
* Temporarily use polling here:
*/
-int i915_wait_fence(drm_device_t * dev, uint32_t fence)
+int i915_wait_fence(drm_device_t * dev, uint32_t type, uint32_t fence)
{
- int i;
+
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ int i;
+ int ret;
if (!dev_priv)
return 0;
+ ret = 1;
for (i=0; i<10000000; ++i) {
- if ( i915_test_fence( dev, fence)) {
+ if ( i915_do_test_fence( dev, fence)) {
+ fence = READ_BREADCRUMB(dev_priv);
i915_sync_flush(dev);
- return 0;
+ ret = 0;
+ break;
}
}
- DRM_ERROR("Fence timeout %d %d\n", READ_BREADCRUMB(dev_priv), fence);
- return 1;
+ if (ret) {
+ DRM_ERROR("Fence timeout %d %d\n",
+ READ_BREADCRUMB(dev_priv), fence);
+ } else {
+ dev->mm_driver->mm_sarea->retired[0] = fence;
+ }
+
+ return ret;
}