From: <th...@ke...> - 2007-02-14 12:32:53
|
linux-core/drmP.h | 9 +++- linux-core/drm_compat.c | 3 + linux-core/drm_fence.c | 92 ++++++++++++++++++++++++++--------------------- linux-core/drm_vm.c | 4 +- linux-core/i915_buffer.c | 4 +- linux-core/i915_drv.c | 1 linux-core/i915_fence.c | 22 ++++++++--- shared-core/i915_drv.h | 6 ++- 8 files changed, 88 insertions(+), 53 deletions(-) New commits: diff-tree 5c9a7b0f9499b94856916facd110059223d243dc (from 04760563b88c8e94f3ae448710d1ab8b350c2e5f) Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> Date: Wed Feb 14 13:31:35 2007 +0100 Remove an intel-specific hack and replace it with a fence driver callback. diff --git a/linux-core/drmP.h b/linux-core/drmP.h index e070c07..e0afc50 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -793,10 +793,11 @@ typedef struct drm_fence_driver{ uint32_t flush_diff; uint32_t sequence_mask; int lazy_capable; - int (*emit) (struct drm_device *dev, uint32_t flags, + int (*has_irq) (struct drm_device *dev, uint32_t class, uint32_t flags); + int (*emit) (struct drm_device *dev, uint32_t class, uint32_t flags, uint32_t *breadcrumb, uint32_t *native_type); - void (*poke_flush) (struct drm_device *dev); + void (*poke_flush) (struct drm_device *dev, uint32_t class); } drm_fence_driver_t; #define _DRM_FENCE_TYPE_EXE 0x00 @@ -1464,7 +1465,8 @@ extern int drm_user_object_unref(drm_fil * fence objects (drm_fence.c) */ -extern void drm_fence_handler(drm_device_t *dev, uint32_t breadcrumb, uint32_t type); +extern void drm_fence_handler(drm_device_t *dev, uint32_t class, + uint32_t sequence, uint32_t type); extern void drm_fence_manager_init(drm_device_t *dev); extern void drm_fence_manager_takedown(drm_device_t *dev); extern void drm_fence_flush_old(drm_device_t *dev, uint32_t sequence); diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index b4125c6..dc42894 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -34,7 +34,8 @@ * Typically called by the IRQ handler. */ -void drm_fence_handler(drm_device_t * dev, uint32_t sequence, uint32_t type) +void drm_fence_handler(drm_device_t * dev, uint32_t class, + uint32_t sequence, uint32_t type) { int wake = 0; uint32_t diff; @@ -156,7 +157,7 @@ static int fence_signaled(drm_device_t * drm_fence_driver_t *driver = dev->driver->fence_driver; if (poke_flush) - driver->poke_flush(dev); + driver->poke_flush(dev, fence->class); read_lock_irqsave(&fm->lock, flags); signaled = (fence->type & mask & fence->signaled) == (fence->type & mask); @@ -177,7 +178,6 @@ static void drm_fence_flush_exe(drm_fenc * Last_exe_flush is invalid. Find oldest sequence. */ -/* list = fm->fence_types[_DRM_FENCE_TYPE_EXE];*/ list = &fm->ring; if (list->next == &fm->ring) { return; @@ -234,7 +234,7 @@ int drm_fence_object_flush(drm_device_t } } write_unlock_irqrestore(&fm->lock, flags); - driver->poke_flush(dev); + driver->poke_flush(dev, fence->class); return 0; } @@ -273,11 +273,37 @@ void drm_fence_flush_old(drm_device_t * EXPORT_SYMBOL(drm_fence_flush_old); +static int drm_fence_lazy_wait(drm_device_t *dev, + volatile drm_fence_object_t *fence, + int ignore_signals, uint32_t mask) +{ + drm_fence_manager_t *fm = &dev->fm; + unsigned long _end = jiffies + 3*DRM_HZ; + int ret = 0; + + do { + DRM_WAIT_ON(ret, fm->fence_queue, 3 * DRM_HZ, + fence_signaled(dev, fence, mask, 1)); + if (time_after_eq(jiffies, _end)) + break; + } while (ret == -EINTR && ignore_signals); + if (time_after_eq(jiffies, _end) && (ret != 0)) + ret = -EBUSY; + if (ret) { + if (ret == -EBUSY) { + DRM_ERROR("Fence timeout. " + "GPU lockup or fence driver was " + "taken down.\n"); + } + return ((ret == -EINTR) ? -EAGAIN : ret); + } + return 0; +} + int drm_fence_object_wait(drm_device_t * dev, volatile drm_fence_object_t * fence, int lazy, int ignore_signals, uint32_t mask) { - drm_fence_manager_t *fm = &dev->fm; drm_fence_driver_t *driver = dev->driver->fence_driver; int ret = 0; unsigned long _end; @@ -298,46 +324,32 @@ int drm_fence_object_wait(drm_device_t * if (lazy && driver->lazy_capable) { - do { - DRM_WAIT_ON(ret, fm->fence_queue, 3 * DRM_HZ, - fence_signaled(dev, fence, mask, 1)); - if (time_after_eq(jiffies, _end)) - break; - } while (ret == -EINTR && ignore_signals); - if (time_after_eq(jiffies, _end) && (ret != 0)) - ret = -EBUSY; - if (ret) { - if (ret == -EBUSY) { - DRM_ERROR("Fence timeout. " - "GPU lockup or fence driver was " - "taken down.\n"); - } - return ((ret == -EINTR) ? -EAGAIN : ret); - } - } else if ((fence->class == 0) && (mask & DRM_FENCE_TYPE_EXE) && - driver->lazy_capable) { + ret = drm_fence_lazy_wait(dev, fence, ignore_signals, mask); + if (ret) + return ret; - /* - * We use IRQ wait for EXE fence if available to gain - * CPU in some cases. - */ + } else { - do { - DRM_WAIT_ON(ret, fm->fence_queue, 3 * DRM_HZ, - fence_signaled(dev, fence, - DRM_FENCE_TYPE_EXE, 1)); - if (time_after_eq(jiffies, _end)) - break; - } while (ret == -EINTR && ignore_signals); - if (time_after_eq(jiffies, _end) && (ret != 0)) - ret = -EBUSY; - if (ret) - return ((ret == -EINTR) ? -EAGAIN : ret); - } + if (driver->has_irq(dev, fence->class, + DRM_FENCE_TYPE_EXE)) { + ret = drm_fence_lazy_wait(dev, fence, ignore_signals, + DRM_FENCE_TYPE_EXE); + if (ret) + return ret; + } + if (driver->has_irq(dev, fence->class, + mask & ~DRM_FENCE_TYPE_EXE)) { + ret = drm_fence_lazy_wait(dev, fence, ignore_signals, + mask); + if (ret) + return ret; + } + } if (fence_signaled(dev, fence, mask, 0)) return 0; + DRM_ERROR("Busy wait\n"); /* * Avoid kernel-space busy-waits. */ @@ -367,7 +379,7 @@ int drm_fence_object_emit(drm_device_t * int ret; drm_fence_unring(dev, &fence->ring); - ret = driver->emit(dev, fence_flags, &sequence, &native_type); + ret = driver->emit(dev, fence->class, fence_flags, &sequence, &native_type); if (ret) return ret; diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index 848ffa7..b7bf883 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -47,6 +47,7 @@ static drm_fence_driver_t i915_fence_dri .lazy_capable = 1, .emit = i915_fence_emit_sequence, .poke_flush = i915_poke_flush, + .has_irq = i915_fence_has_irq, }; #endif #ifdef I915_HAVE_BUFFER diff --git a/linux-core/i915_fence.c b/linux-core/i915_fence.c index 2182604..fa2a3d1 100644 --- a/linux-core/i915_fence.c +++ b/linux-core/i915_fence.c @@ -61,7 +61,7 @@ static void i915_perform_flush(drm_devic diff = sequence - fm->last_exe_flush; if (diff < driver->wrap_diff && diff != 0) { - drm_fence_handler(dev, sequence, DRM_FENCE_TYPE_EXE); + drm_fence_handler(dev, 0, sequence, DRM_FENCE_TYPE_EXE); } diff = sequence - fm->exe_flush_sequence; @@ -84,7 +84,7 @@ static void i915_perform_flush(drm_devic 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); + drm_fence_handler(dev, 0, flush_sequence, flush_flags); } } @@ -104,13 +104,13 @@ static void i915_perform_flush(drm_devic 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); + drm_fence_handler(dev, 0, flush_sequence, flush_flags); } } } -void i915_poke_flush(drm_device_t * dev) +void i915_poke_flush(drm_device_t * dev, uint32_t class) { drm_fence_manager_t *fm = &dev->fm; unsigned long flags; @@ -120,7 +120,7 @@ void i915_poke_flush(drm_device_t * dev) write_unlock_irqrestore(&fm->lock, flags); } -int i915_fence_emit_sequence(drm_device_t * dev, uint32_t flags, +int i915_fence_emit_sequence(drm_device_t * dev, uint32_t class, uint32_t flags, uint32_t * sequence, uint32_t * native_type) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -144,3 +144,15 @@ void i915_fence_handler(drm_device_t * d i915_perform_flush(dev); write_unlock(&fm->lock); } + +int i915_fence_has_irq(drm_device_t *dev, uint32_t class, uint32_t flags) +{ + /* + * We have an irq that tells us when we have a new breadcrumb. + */ + + if (class == 0 && flags == DRM_FENCE_TYPE_EXE) + return 1; + + return 0; +} diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index ffc9d43..675fd16 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -178,10 +178,12 @@ extern void i915_mem_release(drm_device_ extern void i915_fence_handler(drm_device_t *dev); -extern int i915_fence_emit_sequence(drm_device_t *dev, uint32_t flags, +extern int i915_fence_emit_sequence(drm_device_t *dev, uint32_t class, + uint32_t flags, uint32_t *sequence, uint32_t *native_type); -extern void i915_poke_flush(drm_device_t *dev); +extern void i915_poke_flush(drm_device_t *dev, uint32_t class); +extern int i915_fence_has_irq(drm_device_t *dev, uint32_t class, uint32_t flags); #endif #ifdef I915_HAVE_BUFFER diff-tree 04760563b88c8e94f3ae448710d1ab8b350c2e5f (from 7bcb62b45d18ab7b48ad3cb5d13aec3bc577678e) Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> Date: Wed Feb 14 12:39:02 2007 +0100 Set the drm bus map type for each buffer object memory type. diff --git a/linux-core/drmP.h b/linux-core/drmP.h index c472689..e070c07 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -664,6 +664,7 @@ typedef struct drm_mem_type_manager { struct list_head lru; struct list_head pinned; uint32_t flags; + uint32_t drm_bus_maptype; unsigned long io_offset; unsigned long io_size; void *io_addr; diff --git a/linux-core/drm_compat.c b/linux-core/drm_compat.c index eeda4e4..3bb3599 100644 --- a/linux-core/drm_compat.c +++ b/linux-core/drm_compat.c @@ -306,8 +306,9 @@ int drm_bo_map_bound(struct vm_area_stru BUG_ON(ret); if (bus_size) { + drm_mem_type_manager_t *man = &dev->bm.man[bo->mem.mem_type]; unsigned long pfn = (bus_base + bus_offset) >> PAGE_SHIFT; - pgprot_t pgprot = drm_io_prot(_DRM_AGP, vma); + pgprot_t pgprot = drm_io_prot(man->drm_bus_maptype, vma); ret = io_remap_pfn_range(vma, vma->vm_start, pfn, vma->vm_end - vma->vm_start, pgprot); diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 4a340b5..f3b1088 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -816,8 +816,10 @@ struct page *drm_bo_vm_fault(struct vm_a page_offset = (address - vma->vm_start) >> PAGE_SHIFT; if (bus_size) { + drm_mem_type_manager_t *man = &dev->bm.man[bo->mem.mem_type]; + pfn = ((bus_base + bus_offset) >> PAGE_SHIFT) + page_offset; - vma->vm_page_prot = drm_io_prot(_DRM_AGP, vma); + vma->vm_page_prot = drm_io_prot(man->drm_bus_maptype, vma); } else { ttm = bo->ttm; diff --git a/linux-core/i915_buffer.c b/linux-core/i915_buffer.c index 3ccfab3..374b28d 100644 --- a/linux-core/i915_buffer.c +++ b/linux-core/i915_buffer.c @@ -71,6 +71,7 @@ int i915_init_mem_type(drm_device_t * de case DRM_BO_MEM_LOCAL: man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | _DRM_FLAG_MEMTYPE_CACHED; + man->drm_bus_maptype = 0; break; case DRM_BO_MEM_TT: if (!(drm_core_has_AGP(dev) && dev->agp)) { @@ -83,6 +84,7 @@ int i915_init_mem_type(drm_device_t * de man->io_addr = NULL; man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_NEEDS_IOREMAP; + man->drm_bus_maptype = _DRM_AGP; break; case DRM_BO_MEM_PRIV0: if (!(drm_core_has_AGP(dev) && dev->agp)) { @@ -95,7 +97,7 @@ int i915_init_mem_type(drm_device_t * de man->io_addr = NULL; man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | _DRM_FLAG_MEMTYPE_FIXED | _DRM_FLAG_NEEDS_IOREMAP; - + man->drm_bus_maptype = _DRM_AGP; break; default: DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); |