Initial support for fence object classes.

(Fence objects belonging to different command submission mechanisms).
main
Thomas Hellstrom 2007-02-15 12:10:33 +01:00
parent 7803977aa9
commit 7766378d97
9 changed files with 93 additions and 70 deletions

View File

@ -2267,7 +2267,7 @@ int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data,
* DRM_FENCE_MASK_DRIVER
*/
int drmFenceCreate(int fd, unsigned flags, int class,unsigned type,
int drmFenceCreate(int fd, unsigned flags, int class, unsigned type,
drmFence *fence)
{
drm_fence_arg_t arg;
@ -2410,8 +2410,9 @@ int drmFenceSignaled(int fd, drmFence *fence, unsigned fenceType,
int drmFenceEmit(int fd, unsigned flags, drmFence *fence, unsigned emit_type)
{
drm_fence_arg_t arg;
memset(&arg, 0, sizeof(arg));
arg.class = fence->class;
arg.flags = flags;
arg.handle = fence->handle;
arg.type = emit_type;

View File

@ -561,7 +561,7 @@ int drm_fence_buffer_objects(drm_file_t * priv,
}
} else {
mutex_unlock(&dev->struct_mutex);
ret = drm_fence_object_create(dev, fence_type,
ret = drm_fence_object_create(dev, 0, fence_type,
fence_flags | DRM_FENCE_FLAG_EMIT,
&fence);
mutex_lock(&dev->struct_mutex);

View File

@ -326,6 +326,7 @@ int drm_buffer_object_transfer(drm_buffer_object_t * bo,
int drm_bo_move_accel_cleanup(drm_buffer_object_t * bo,
int evict,
int no_wait,
uint32_t fence_class,
uint32_t fence_type,
uint32_t fence_flags, drm_bo_mem_reg_t * new_mem)
{
@ -339,7 +340,7 @@ int drm_bo_move_accel_cleanup(drm_buffer_object_t * bo,
if (bo->fence)
drm_fence_usage_deref_unlocked(dev, bo->fence);
ret = drm_fence_object_create(dev, fence_type,
ret = drm_fence_object_create(dev, fence_class, fence_type,
fence_flags | DRM_FENCE_FLAG_EMIT,
&bo->fence);
if (ret)

View File

@ -41,15 +41,16 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class,
uint32_t diff;
uint32_t relevant;
drm_fence_manager_t *fm = &dev->fm;
drm_fence_class_manager_t *fc = &fm->class[class];
drm_fence_driver_t *driver = dev->driver->fence_driver;
struct list_head *list, *prev;
drm_fence_object_t *fence;
int found = 0;
if (list_empty(&fm->ring))
if (list_empty(&fc->ring))
return;
list_for_each_entry(fence, &fm->ring, ring) {
list_for_each_entry(fence, &fc->ring, ring) {
diff = (sequence - fence->sequence) & driver->sequence_mask;
if (diff > driver->wrap_diff) {
found = 1;
@ -57,10 +58,10 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class,
}
}
list = (found) ? fence->ring.prev : fm->ring.prev;
list = (found) ? fence->ring.prev : fc->ring.prev;
prev = list->prev;
for (; list != &fm->ring; list = prev, prev = list->prev) {
for (; list != &fc->ring; list = prev, prev = list->prev) {
fence = list_entry(list, drm_fence_object_t, ring);
type |= fence->native_type;
@ -78,7 +79,7 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class,
~(fence->signaled | fence->submitted_flush);
if (relevant) {
fm->pending_flush |= relevant;
fc->pending_flush |= relevant;
fence->submitted_flush = fence->flush_mask;
}
@ -91,7 +92,7 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class,
}
if (wake) {
DRM_WAKEUP(&fm->fence_queue);
DRM_WAKEUP(&fc->fence_queue);
}
}
@ -166,37 +167,37 @@ static int fence_signaled(drm_device_t * dev,
return signaled;
}
static void drm_fence_flush_exe(drm_fence_manager_t * fm,
static void drm_fence_flush_exe(drm_fence_class_manager_t * fc,
drm_fence_driver_t * driver, uint32_t sequence)
{
uint32_t diff;
if (!fm->pending_exe_flush) {
if (!fc->pending_exe_flush) {
struct list_head *list;
/*
* Last_exe_flush is invalid. Find oldest sequence.
*/
list = &fm->ring;
if (list->next == &fm->ring) {
list = &fc->ring;
if (list->next == &fc->ring) {
return;
} else {
drm_fence_object_t *fence =
list_entry(list->next, drm_fence_object_t, ring);
fm->last_exe_flush = (fence->sequence - 1) &
fc->last_exe_flush = (fence->sequence - 1) &
driver->sequence_mask;
}
diff = (sequence - fm->last_exe_flush) & driver->sequence_mask;
diff = (sequence - fc->last_exe_flush) & driver->sequence_mask;
if (diff >= driver->wrap_diff)
return;
fm->exe_flush_sequence = sequence;
fm->pending_exe_flush = 1;
fc->exe_flush_sequence = sequence;
fc->pending_exe_flush = 1;
} else {
diff =
(sequence - fm->exe_flush_sequence) & driver->sequence_mask;
(sequence - fc->exe_flush_sequence) & driver->sequence_mask;
if (diff < driver->wrap_diff) {
fm->exe_flush_sequence = sequence;
fc->exe_flush_sequence = sequence;
}
}
}
@ -212,6 +213,7 @@ int drm_fence_object_flush(drm_device_t * dev,
uint32_t type)
{
drm_fence_manager_t *fm = &dev->fm;
drm_fence_class_manager_t *fc = &fm->class[fence->class];
drm_fence_driver_t *driver = dev->driver->fence_driver;
unsigned long flags;
@ -226,10 +228,10 @@ int drm_fence_object_flush(drm_device_t * dev,
if (fence->submitted_flush == fence->signaled) {
if ((fence->type & DRM_FENCE_TYPE_EXE) &&
!(fence->submitted_flush & DRM_FENCE_TYPE_EXE)) {
drm_fence_flush_exe(fm, driver, fence->sequence);
drm_fence_flush_exe(fc, driver, fence->sequence);
fence->submitted_flush |= DRM_FENCE_TYPE_EXE;
} else {
fm->pending_flush |= (fence->flush_mask &
fc->pending_flush |= (fence->flush_mask &
~fence->submitted_flush);
fence->submitted_flush = fence->flush_mask;
}
@ -244,9 +246,10 @@ int drm_fence_object_flush(drm_device_t * dev,
* wrapped around and reused.
*/
void drm_fence_flush_old(drm_device_t * dev, uint32_t sequence)
void drm_fence_flush_old(drm_device_t * dev, uint32_t class, uint32_t sequence)
{
drm_fence_manager_t *fm = &dev->fm;
drm_fence_class_manager_t *fc = &fm->class[class];
drm_fence_driver_t *driver = dev->driver->fence_driver;
uint32_t old_sequence;
unsigned long flags;
@ -255,13 +258,13 @@ void drm_fence_flush_old(drm_device_t * dev, uint32_t sequence)
mutex_lock(&dev->struct_mutex);
read_lock_irqsave(&fm->lock, flags);
if (fm->ring.next == &fm->ring) {
if (fc->ring.next == &fc->ring) {
read_unlock_irqrestore(&fm->lock, flags);
mutex_unlock(&dev->struct_mutex);
return;
}
old_sequence = (sequence - driver->flush_diff) & driver->sequence_mask;
fence = list_entry(fm->ring.next, drm_fence_object_t, ring);
fence = list_entry(fc->ring.next, drm_fence_object_t, ring);
atomic_inc(&fence->usage);
mutex_unlock(&dev->struct_mutex);
diff = (old_sequence - fence->sequence) & driver->sequence_mask;
@ -279,11 +282,13 @@ static int drm_fence_lazy_wait(drm_device_t *dev,
int ignore_signals, uint32_t mask)
{
drm_fence_manager_t *fm = &dev->fm;
drm_fence_class_manager_t *fc = &fm->class[fence->class];
unsigned long _end = jiffies + 3*DRM_HZ;
int ret = 0;
do {
DRM_WAIT_ON(ret, fm->fence_queue, 3 * DRM_HZ,
DRM_WAIT_ON(ret, fc->fence_queue, 3 * DRM_HZ,
fence_signaled(dev, fence, mask, 1));
if (time_after_eq(jiffies, _end))
break;
@ -370,7 +375,7 @@ int drm_fence_object_wait(drm_device_t * dev,
}
int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence,
uint32_t fence_flags, uint32_t type)
uint32_t fence_flags, uint32_t class, uint32_t type)
{
drm_fence_manager_t *fm = &dev->fm;
drm_fence_driver_t *driver = dev->driver->fence_driver;
@ -380,23 +385,25 @@ int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence,
int ret;
drm_fence_unring(dev, &fence->ring);
ret = driver->emit(dev, fence->class, fence_flags, &sequence, &native_type);
ret = driver->emit(dev, class, fence_flags, &sequence, &native_type);
if (ret)
return ret;
write_lock_irqsave(&fm->lock, flags);
fence->class = class;
fence->type = type;
fence->flush_mask = 0x00;
fence->submitted_flush = 0x00;
fence->signaled = 0x00;
fence->sequence = sequence;
fence->native_type = native_type;
list_add_tail(&fence->ring, &fm->ring);
list_add_tail(&fence->ring, &fm->class[class].ring);
write_unlock_irqrestore(&fm->lock, flags);
return 0;
}
static int drm_fence_object_init(drm_device_t * dev, uint32_t type,
static int drm_fence_object_init(drm_device_t * dev, uint32_t class,
uint32_t type,
uint32_t fence_flags,
drm_fence_object_t * fence)
{
@ -410,7 +417,7 @@ static int drm_fence_object_init(drm_device_t * dev, uint32_t type,
write_lock_irqsave(&fm->lock, flags);
INIT_LIST_HEAD(&fence->ring);
fence->class = 0;
fence->class = class;
fence->type = type;
fence->flush_mask = 0;
fence->submitted_flush = 0;
@ -418,7 +425,8 @@ static int drm_fence_object_init(drm_device_t * dev, uint32_t type,
fence->sequence = 0;
write_unlock_irqrestore(&fm->lock, flags);
if (fence_flags & DRM_FENCE_FLAG_EMIT) {
ret = drm_fence_object_emit(dev, fence, fence_flags, type);
ret = drm_fence_object_emit(dev, fence, fence_flags,
fence->class, type);
}
return ret;
}
@ -442,7 +450,7 @@ int drm_fence_add_user_object(drm_file_t * priv, drm_fence_object_t * fence,
EXPORT_SYMBOL(drm_fence_add_user_object);
int drm_fence_object_create(drm_device_t * dev, uint32_t type,
int drm_fence_object_create(drm_device_t * dev, uint32_t class, uint32_t type,
unsigned flags, drm_fence_object_t ** c_fence)
{
drm_fence_object_t *fence;
@ -452,7 +460,7 @@ int drm_fence_object_create(drm_device_t * dev, uint32_t type,
fence = drm_ctl_alloc(sizeof(*fence), DRM_MEM_FENCE);
if (!fence)
return -ENOMEM;
ret = drm_fence_object_init(dev, type, flags, fence);
ret = drm_fence_object_init(dev, class, type, flags, fence);
if (ret) {
drm_fence_usage_deref_unlocked(dev, fence);
return ret;
@ -468,22 +476,31 @@ EXPORT_SYMBOL(drm_fence_object_create);
void drm_fence_manager_init(drm_device_t * dev)
{
drm_fence_manager_t *fm = &dev->fm;
drm_fence_class_manager_t *class;
drm_fence_driver_t *fed = dev->driver->fence_driver;
int i;
fm->lock = RW_LOCK_UNLOCKED;
write_lock(&fm->lock);
INIT_LIST_HEAD(&fm->ring);
fm->pending_flush = 0;
DRM_INIT_WAITQUEUE(&fm->fence_queue);
fm->initialized = 0;
if (fed) {
fm->initialized = 1;
atomic_set(&fm->count, 0);
for (i = 0; i < fed->no_types; ++i) {
fm->fence_types[i] = &fm->ring;
}
if (!fed)
goto out_unlock;
fm->initialized = 1;
fm->num_classes = fed->num_classes;
BUG_ON(fm->num_classes > _DRM_FENCE_CLASSES);
for (i=0; i<fm->num_classes; ++i) {
class = &fm->class[i];
INIT_LIST_HEAD(&class->ring);
class->pending_flush = 0;
DRM_INIT_WAITQUEUE(&class->fence_queue);
}
atomic_set(&fm->count, 0);
out_unlock:
write_unlock(&fm->lock);
}
@ -530,7 +547,8 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS)
case drm_fence_create:
if (arg.flags & DRM_FENCE_FLAG_EMIT)
LOCK_TEST_WITH_RETURN(dev, filp);
ret = drm_fence_object_create(dev, arg.type, arg.flags, &fence);
ret = drm_fence_object_create(dev, arg.class,
arg.type, arg.flags, &fence);
if (ret)
return ret;
ret = drm_fence_add_user_object(priv, fence,
@ -593,7 +611,8 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS)
fence = drm_lookup_fence_object(priv, arg.handle);
if (!fence)
return -EINVAL;
ret = drm_fence_object_emit(dev, fence, arg.flags, arg.type);
ret = drm_fence_object_emit(dev, fence, arg.flags, arg.class,
arg.type);
break;
case drm_fence_buffers:
if (!dev->bm.initialized) {

View File

@ -158,29 +158,28 @@ typedef struct drm_fence_object {
uint32_t submitted_flush;
} drm_fence_object_t;
#define _DRM_FENCE_CLASSES 8
#define _DRM_FENCE_TYPE_EXE 0x00
typedef struct drm_fence_manager {
int initialized;
rwlock_t lock;
/*
* The list below should be maintained in sequence order and
* access is protected by the above spinlock.
*/
typedef struct drm_fence_class_manager {
struct list_head ring;
struct list_head *fence_types[32];
volatile uint32_t pending_flush;
uint32_t pending_flush;
wait_queue_head_t fence_queue;
int pending_exe_flush;
uint32_t last_exe_flush;
uint32_t exe_flush_sequence;
} drm_fence_class_manager_t;
typedef struct drm_fence_manager {
int initialized;
rwlock_t lock;
drm_fence_class_manager_t class[_DRM_FENCE_CLASSES];
uint32_t num_classes;
atomic_t count;
} drm_fence_manager_t;
typedef struct drm_fence_driver {
int no_types;
uint32_t num_classes;
uint32_t wrap_diff;
uint32_t flush_diff;
uint32_t sequence_mask;
@ -196,7 +195,8 @@ extern void drm_fence_handler(struct drm_device *dev, uint32_t class,
uint32_t sequence, uint32_t type);
extern void drm_fence_manager_init(struct drm_device *dev);
extern void drm_fence_manager_takedown(struct drm_device *dev);
extern void drm_fence_flush_old(struct drm_device *dev, uint32_t sequence);
extern void drm_fence_flush_old(struct drm_device *dev, uint32_t class,
uint32_t sequence);
extern int drm_fence_object_flush(struct drm_device *dev,
drm_fence_object_t * fence, uint32_t type);
extern int drm_fence_object_signaled(drm_fence_object_t * fence, uint32_t type);
@ -208,7 +208,7 @@ extern int drm_fence_object_wait(struct drm_device *dev,
drm_fence_object_t * fence,
int lazy, int ignore_signals, uint32_t mask);
extern int drm_fence_object_create(struct drm_device *dev, uint32_t type,
uint32_t fence_flags,
uint32_t fence_flags, uint32_t class,
drm_fence_object_t ** c_fence);
extern int drm_fence_add_user_object(drm_file_t * priv,
drm_fence_object_t * fence, int shareable);
@ -462,6 +462,7 @@ extern int drm_bo_move_memcpy(drm_buffer_object_t * bo,
extern int drm_bo_move_accel_cleanup(drm_buffer_object_t * bo,
int evict,
int no_wait,
uint32_t fence_class,
uint32_t fence_type,
uint32_t fence_flags,
drm_bo_mem_reg_t * new_mem);

View File

@ -170,7 +170,7 @@ static int i915_move_blit(drm_buffer_object_t * bo,
i915_emit_mi_flush(bo->dev, MI_READ_FLUSH | MI_EXE_FLUSH);
return drm_bo_move_accel_cleanup(bo, evict, no_wait,
return drm_bo_move_accel_cleanup(bo, evict, no_wait, 0,
DRM_FENCE_TYPE_EXE |
DRM_I915_FENCE_TYPE_RW,
DRM_I915_FENCE_FLAG_FLUSHED, new_mem);

View File

@ -40,7 +40,7 @@ static struct pci_device_id pciidlist[] = {
#ifdef I915_HAVE_FENCE
static drm_fence_driver_t i915_fence_driver = {
.no_types = 2,
.num_classes = 1,
.wrap_diff = (1 << 30),
.flush_diff = (1 << 29),
.sequence_mask = 0xffffffffU,

View File

@ -42,6 +42,7 @@ 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_class_manager_t *fc = &fm->class[0];
drm_fence_driver_t *driver = dev->driver->fence_driver;
uint32_t flush_flags = 0;
uint32_t flush_sequence = 0;
@ -52,21 +53,21 @@ static void i915_perform_flush(drm_device_t * dev)
if (!dev_priv)
return;
if (fm->pending_exe_flush) {
if (fc->pending_exe_flush) {
sequence = READ_BREADCRUMB(dev_priv);
/*
* First update fences with the current breadcrumb.
*/
diff = sequence - fm->last_exe_flush;
diff = sequence - fc->last_exe_flush;
if (diff < driver->wrap_diff && diff != 0) {
drm_fence_handler(dev, 0, sequence, DRM_FENCE_TYPE_EXE);
}
diff = sequence - fm->exe_flush_sequence;
diff = sequence - fc->exe_flush_sequence;
if (diff < driver->wrap_diff) {
fm->pending_exe_flush = 0;
fc->pending_exe_flush = 0;
if (dev_priv->fence_irq_on) {
i915_user_irq_off(dev_priv);
dev_priv->fence_irq_on = 0;
@ -88,13 +89,13 @@ static void i915_perform_flush(drm_device_t * dev)
}
}
if (fm->pending_flush && !dev_priv->flush_pending) {
if (fc->pending_flush && !dev_priv->flush_pending) {
dev_priv->flush_sequence = (uint32_t) READ_BREADCRUMB(dev_priv);
dev_priv->flush_flags = fm->pending_flush;
dev_priv->flush_flags = fc->pending_flush;
dev_priv->saved_flush_status = READ_HWSP(dev_priv, 0);
I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21));
dev_priv->flush_pending = 1;
fm->pending_flush = 0;
fc->pending_flush = 0;
}
if (dev_priv->flush_pending) {

View File

@ -443,7 +443,7 @@ static void i915_emit_breadcrumb(drm_device_t *dev)
OUT_RING(0);
ADVANCE_LP_RING();
#ifdef I915_HAVE_FENCE
drm_fence_flush_old(dev, dev_priv->counter);
drm_fence_flush_old(dev, 0, dev_priv->counter);
#endif
}
@ -590,7 +590,7 @@ static int i915_dispatch_flip(drm_device_t * dev)
OUT_RING(0);
ADVANCE_LP_RING();
#ifdef I915_HAVE_FENCE
drm_fence_flush_old(dev, dev_priv->counter);
drm_fence_flush_old(dev, 0, dev_priv->counter);
#endif
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
return 0;