diff options
author | Thomas Hellstrom <thomas@tungstengraphics.com> | 2006-02-28 23:48:34 +0000 |
---|---|---|
committer | Thomas Hellstrom <thomas@tungstengraphics.com> | 2006-02-28 23:48:34 +0000 |
commit | 71c507586709e12142dad95d7a56b026c4448f84 (patch) | |
tree | 00936d3d42c901435dc15e8df2beda061c1c63ef | |
parent | 2639c7af46c15ca08a9504ac0915d70bb3dcfe9a (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.h | 9 | ||||
-rw-r--r-- | linux-core/drm_fops.c | 18 | ||||
-rw-r--r-- | linux-core/drm_ttm.c | 106 | ||||
-rw-r--r-- | linux-core/drm_ttm.h | 1 | ||||
-rw-r--r-- | linux-core/i915_ttm.c | 1 | ||||
-rw-r--r-- | shared-core/drm.h | 39 | ||||
-rw-r--r-- | shared-core/i915_drv.h | 6 | ||||
-rw-r--r-- | shared-core/i915_irq.c | 54 |
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; } |