From: <al...@ke...> - 2008-02-19 15:21:48
|
linux-core/drmP.h | 2 linux-core/drm_bo.c | 34 ++- linux-core/drm_fence.c | 392 ++++++++++++++++++++------------------------ linux-core/drm_irq.c | 29 ++- linux-core/drm_objects.h | 76 +++++++- linux-core/i915_drv.c | 51 +++-- linux-core/i915_fence.c | 244 +++++++++++++++++++-------- linux-core/nouveau_buffer.c | 3 linux-core/nouveau_fence.c | 32 +-- linux-core/via_fence.c | 116 +++---------- linux-core/xgi_drv.c | 11 - linux-core/xgi_fence.c | 55 ++---- shared-core/drm_pciids.txt | 2 shared-core/i915_dma.c | 95 +++++++++- shared-core/i915_drm.h | 9 - shared-core/i915_drv.h | 33 ++- shared-core/i915_init.c | 13 + shared-core/mach64_irq.c | 45 +++-- shared-core/nouveau_fifo.c | 1 shared-core/nouveau_mem.c | 4 shared-core/nouveau_reg.h | 25 +- shared-core/nouveau_state.c | 1 shared-core/nv20_graph.c | 45 +++-- shared-core/nv40_fb.c | 7 shared-core/nv40_graph.c | 4 shared-core/radeon_cp.c | 86 +++++++++ shared-core/radeon_drv.h | 42 ++++ shared-core/via_drv.c | 14 - shared-core/via_drv.h | 11 - shared-core/via_map.c | 3 30 files changed, 927 insertions(+), 558 deletions(-) New commits: commit 8caf6e95712bfae8d1a42ffabafcbb9686766116 Author: Alan Hourihane <al...@tu...> Date: Tue Feb 19 15:17:24 2008 +0000 Fix up conflicts for DRI2 (untested) diff --git a/linux-core/i915_fence.c b/linux-core/i915_fence.c index de64a4f..0f6cdee 100644 --- a/linux-core/i915_fence.c +++ b/linux-core/i915_fence.c @@ -94,7 +94,7 @@ static void i915_fence_flush(struct drm_device *dev, static void i915_fence_poll(struct drm_device *dev, uint32_t fence_class, uint32_t waiting_types) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; struct drm_fence_manager *fm = &dev->fm; struct drm_fence_class_manager *fc = &fm->fence_class[0]; uint32_t sequence; @@ -147,7 +147,7 @@ static int i915_fence_emit_sequence(struct drm_device *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; + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; if (unlikely(!dev_priv)) return -EINVAL; @@ -179,7 +179,7 @@ static int i915_fence_wait(struct drm_fence_object *fence, int lazy, int interruptible, uint32_t mask) { struct drm_device *dev = fence->dev; - drm_i915_private_t *dev_priv = (struct drm_i915_private *) dev->dev_private; + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; struct drm_fence_manager *fm = &dev->fm; struct drm_fence_class_manager *fc = &fm->fence_class[0]; int ret; diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 3d48923..11c000b 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -101,7 +101,7 @@ setup_dri2_sarea(struct drm_device * dev, struct drm_file *file_priv, drm_i915_init_t * init) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; int ret; unsigned int *p, *end, *next; @@ -129,8 +129,8 @@ setup_dri2_sarea(struct drm_device * dev, while (p < end && DRI2_SAREA_BLOCK_TYPE(*p) != DRI2_SAREA_BLOCK_END) { switch (DRI2_SAREA_BLOCK_TYPE(*p)) { case DRI2_SAREA_BLOCK_LOCK: - dev->lock.hw_lock = (void *) (p + 1); - dev->sigdata.lock = dev->lock.hw_lock; + dev->primary->master->lock.hw_lock = (void *) (p + 1); + dev->sigdata.lock = dev->primary->master->lock.hw_lock; break; } next = DRI2_SAREA_BLOCK_NEXT(p); @@ -152,6 +152,7 @@ static int i915_initialize(struct drm_device * dev, { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; + dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset); if (!dev_priv->mmio_map) { i915_dma_cleanup(dev); @@ -228,14 +229,13 @@ static int i915_initialize(struct drm_device * dev, #endif if (init->func == I915_INIT_DMA2) { - ret = setup_dri2_sarea(dev, file_priv, init); + int ret = setup_dri2_sarea(dev, file_priv, init); if (ret) { i915_dma_cleanup(dev); DRM_ERROR("could not set up dri2 sarea\n"); return ret; } } - return 0; } @@ -1390,34 +1390,6 @@ static int i915_set_status_page(struct drm_device *dev, void *data, return 0; } -#if 0 /* FIXME DRI2 */ -void i915_driver_lastclose(struct drm_device * dev) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - - if (drm_getsarea(dev) && dev_priv->sarea_priv) - i915_do_cleanup_pageflip(dev); - if (dev_priv->agp_heap) - i915_mem_takedown(&(dev_priv->agp_heap)); - - if (dev_priv->sarea_kmap.virtual) { - drm_bo_kunmap(&dev_priv->sarea_kmap); - dev_priv->sarea_kmap.virtual = NULL; - dev->lock.hw_lock = NULL; - dev->sigdata.lock = NULL; - } - - if (dev_priv->sarea_bo) { - mutex_lock(&dev->struct_mutex); - drm_bo_usage_deref_locked(&dev_priv->sarea_bo); - mutex_unlock(&dev->struct_mutex); - dev_priv->sarea_bo = NULL; - } - - i915_dma_cleanup(dev); -} -#endif - struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH), diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c index c2d8964..fe2fb38 100644 --- a/shared-core/i915_init.c +++ b/shared-core/i915_init.c @@ -269,6 +269,19 @@ int i915_driver_unload(struct drm_device *dev) drm_core_ioremapfree(&dev_priv->ring.map, dev); } #endif + if (dev_priv->sarea_kmap.virtual) { + drm_bo_kunmap(&dev_priv->sarea_kmap); + dev_priv->sarea_kmap.virtual = NULL; + dev->primary->master->lock.hw_lock = NULL; + dev->sigdata.lock = NULL; + } + + if (dev_priv->sarea_bo) { + mutex_lock(&dev->struct_mutex); + drm_bo_usage_deref_locked(&dev_priv->sarea_bo); + mutex_unlock(&dev->struct_mutex); + dev_priv->sarea_bo = NULL; + } if (dev_priv->status_page_dmah) { drm_pci_free(dev, dev_priv->status_page_dmah); commit f24ed2ad6c66e50268fd175146a1661ae4bbd350 Merge: 2b1c9cd... 5d8c754... Author: Alan Hourihane <al...@tu...> Date: Mon Feb 18 22:35:46 2008 +0000 Merge branch 'master' of git+ssh://git.freedesktop.org/git/mesa/drm into modesetting-101 Conflicts: linux-core/i915_fence.c linux-core/via_fence.c shared-core/i915_dma.c shared-core/i915_drv.h shared-core/i915_irq.c diff --cc linux-core/i915_drv.c index 1f84164,9d8b468..64c805f --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@@ -40,21 -39,13 +40,13 @@@ static struct pci_device_id pciidlist[ }; #ifdef I915_HAVE_FENCE - static struct drm_fence_driver i915_fence_driver = { - .num_classes = 1, - .wrap_diff = (1U << (BREADCRUMB_BITS - 1)), - .flush_diff = (1U << (BREADCRUMB_BITS - 2)), - .sequence_mask = BREADCRUMB_MASK, - .lazy_capable = 1, - .emit = i915_fence_emit_sequence, - .poke_flush = i915_poke_flush, - .has_irq = i915_fence_has_irq, - }; + extern struct drm_fence_driver i915_fence_driver; #endif + #ifdef I915_HAVE_BUFFER -static uint32_t i915_mem_prios[] = {DRM_BO_MEM_PRIV0, DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL}; -static uint32_t i915_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_PRIV0, DRM_BO_MEM_LOCAL}; +static uint32_t i915_mem_prios[] = {DRM_BO_MEM_VRAM, DRM_BO_MEM_PRIV0, DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL}; +static uint32_t i915_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_PRIV0, DRM_BO_MEM_VRAM, DRM_BO_MEM_LOCAL}; static struct drm_bo_driver i915_bo_driver = { .mem_type_prio = i915_mem_prios, diff --cc shared-core/i915_dma.c index 0a3d82a,3874ed5..3d48923 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@@ -85,11 -86,103 +85,74 @@@ int i915_dma_cleanup(struct drm_device - if (dev_priv->ring.virtual_start) { - drm_core_ioremapfree(&dev_priv->ring.map, dev); - dev_priv->ring.virtual_start = 0; - dev_priv->ring.map.handle = 0; - dev_priv->ring.map.size = 0; - } - - if (dev_priv->status_page_dmah) { - drm_pci_free(dev, dev_priv->status_page_dmah); - dev_priv->status_page_dmah = NULL; - /* Need to rewrite hardware status page */ - I915_WRITE(0x02080, 0x1ffff000); - } - - if (dev_priv->status_gfx_addr) { - dev_priv->status_gfx_addr = 0; - drm_core_ioremapfree(&dev_priv->hws_map, dev); - I915_WRITE(0x02080, 0x1ffff000); - } - return 0; } - static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) + + #define DRI2_SAREA_BLOCK_TYPE(b) ((b) >> 16) + #define DRI2_SAREA_BLOCK_SIZE(b) ((b) & 0xffff) + #define DRI2_SAREA_BLOCK_NEXT(p) \ + ((void *) ((unsigned char *) (p) + \ + DRI2_SAREA_BLOCK_SIZE(*(unsigned int *) p))) + + #define DRI2_SAREA_BLOCK_END 0x0000 + #define DRI2_SAREA_BLOCK_LOCK 0x0001 + #define DRI2_SAREA_BLOCK_EVENT_BUFFER 0x0002 + + static int + setup_dri2_sarea(struct drm_device * dev, + struct drm_file *file_priv, + drm_i915_init_t * init) + { + drm_i915_private_t *dev_priv = dev->dev_private; + int ret; + unsigned int *p, *end, *next; + + mutex_lock(&dev->struct_mutex); + dev_priv->sarea_bo = + drm_lookup_buffer_object(file_priv, + init->sarea_handle, 1); + mutex_unlock(&dev->struct_mutex); + + if (!dev_priv->sarea_bo) { + DRM_ERROR("did not find sarea bo\n"); + return -EINVAL; + } + + ret = drm_bo_kmap(dev_priv->sarea_bo, 0, + dev_priv->sarea_bo->num_pages, + &dev_priv->sarea_kmap); + if (ret) { + DRM_ERROR("could not map sarea bo\n"); + return ret; + } + + p = dev_priv->sarea_kmap.virtual; + end = (void *) p + (dev_priv->sarea_bo->num_pages << PAGE_SHIFT); + while (p < end && DRI2_SAREA_BLOCK_TYPE(*p) != DRI2_SAREA_BLOCK_END) { + switch (DRI2_SAREA_BLOCK_TYPE(*p)) { + case DRI2_SAREA_BLOCK_LOCK: + dev->lock.hw_lock = (void *) (p + 1); + dev->sigdata.lock = dev->lock.hw_lock; + break; + } + next = DRI2_SAREA_BLOCK_NEXT(p); + if (next <= p || end < next) { + DRM_ERROR("malformed dri2 sarea: next is %p should be within %p-%p\n", + next, p, end); + return -EINVAL; + } + p = next; + } + + return 0; + } + + + static int i915_initialize(struct drm_device * dev, + struct drm_file *file_priv, + drm_i915_init_t * init) { - drm_i915_private_t *dev_priv = dev->dev_private; - int ret; - - dev_priv->sarea = drm_getsarea(dev); - if (!dev_priv->sarea) { - DRM_ERROR("can not find sarea!\n"); - i915_dma_cleanup(dev); - return -EINVAL; - } - - if (init->mmio_offset != 0) - dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset); + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; + dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset); if (!dev_priv->mmio_map) { i915_dma_cleanup(dev); DRM_ERROR("can not find mmio map!\n"); @@@ -1309,6 -1428,92 +1390,34 @@@ static int i915_set_status_page(struct return 0; } -int i915_driver_load(struct drm_device *dev, unsigned long flags) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - unsigned long base, size; - int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1; - - /* i915 has 4 more counters */ - dev->counters += 4; - dev->types[6] = _DRM_STAT_IRQ; - dev->types[7] = _DRM_STAT_PRIMARY; - dev->types[8] = _DRM_STAT_SECONDARY; - dev->types[9] = _DRM_STAT_DMA; - - dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER); - if (dev_priv == NULL) - return -ENOMEM; - - memset(dev_priv, 0, sizeof(drm_i915_private_t)); - - dev->dev_private = (void *)dev_priv; - - /* Add register map (needed for suspend/resume) */ - base = drm_get_resource_start(dev, mmio_bar); - size = drm_get_resource_len(dev, mmio_bar); - - ret = drm_addmap(dev, base, size, _DRM_REGISTERS, - _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio_map); - -#ifdef __linux__ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) - intel_init_chipset_flush_compat(dev); -#endif -#endif - - return ret; -} - -int i915_driver_unload(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (dev_priv->mmio_map) - drm_rmmap(dev, dev_priv->mmio_map); - - drm_free(dev->dev_private, sizeof(drm_i915_private_t), - DRM_MEM_DRIVER); -#ifdef __linux__ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) - intel_fini_chipset_flush_compat(dev); -#endif -#endif - return 0; -} - ++#if 0 /* FIXME DRI2 */ + void i915_driver_lastclose(struct drm_device * dev) + { + drm_i915_private_t *dev_priv = dev->dev_private; + + if (drm_getsarea(dev) && dev_priv->sarea_priv) + i915_do_cleanup_pageflip(dev); + if (dev_priv->agp_heap) + i915_mem_takedown(&(dev_priv->agp_heap)); + + if (dev_priv->sarea_kmap.virtual) { + drm_bo_kunmap(&dev_priv->sarea_kmap); + dev_priv->sarea_kmap.virtual = NULL; + dev->lock.hw_lock = NULL; + dev->sigdata.lock = NULL; + } + + if (dev_priv->sarea_bo) { + mutex_lock(&dev->struct_mutex); + drm_bo_usage_deref_locked(&dev_priv->sarea_bo); + mutex_unlock(&dev->struct_mutex); + dev_priv->sarea_bo = NULL; + } + + i915_dma_cleanup(dev); + } - -void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - i915_mem_release(dev, file_priv, dev_priv->agp_heap); -} ++#endif + struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH), diff --cc shared-core/i915_drm.h index d48d766,b889a30..6067fa0 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@@ -61,9 -66,10 +66,10 @@@ typedef struct drm_i915_init unsigned int depth_pitch; unsigned int cpp; unsigned int chipset; + unsigned int sarea_handle; } drm_i915_init_t; -typedef struct _drm_i915_sarea { +typedef struct drm_i915_sarea { struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1]; int last_upload; /* last time texture was uploaded */ int last_enqueue; /* last time a buffer was enqueued */ diff --cc shared-core/i915_drv.h index 1432806,4d3ac0a..f6c0005 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@@ -156,15 -144,14 +156,19 @@@ struct drm_i915_private #endif DRM_SPINTYPE swaps_lock; - drm_i915_vbl_swap_t vbl_swaps; + struct drm_i915_vbl_swap vbl_swaps; unsigned int swaps_pending; + /* LVDS info */ + int backlight_duty_cycle; /* restore backlight to this value */ + bool panel_wants_dither; + struct drm_display_mode *panel_fixed_mode; + - /* Register state */ + /* DRI2 sarea */ + struct drm_buffer_object *sarea_bo; + struct drm_bo_kmap_obj sarea_kmap; + + /* Register state */ u8 saveLBB; u32 saveDSPACNTR; u32 saveDSPBCNTR; commit 5d8c754bc2c720d70bbdeca6b294660105717a62 Author: Keith Packard <ke...@ke...> Date: Sat Feb 16 19:19:29 2008 -0800 [915]: more registers for S3 (DSPCLK_GATE_D, CACHE_MODE_0, MI_ARB_STATE) Failing to preserve the MI_ARB_STATE register was causing FIFO underruns on the VGA output on my HP 2510p after resume. diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index 3e2bfc9..9d8b468 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -369,6 +369,15 @@ static int i915_suspend(struct drm_device *dev) dev_priv->saveVCLK_POST_DIV = I915_READ(VCLK_POST_DIV); dev_priv->saveVGACNTRL = I915_READ(VGACNTRL); + /* Clock gating state */ + dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D); + + /* Cache mode state */ + dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); + + /* Memory Arbitration state */ + dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE); + /* Scratch space */ for (i = 0; i < 16; i++) { dev_priv->saveSWF0[i] = I915_READ(SWF0 + (i << 2)); @@ -516,6 +525,15 @@ static int i915_resume(struct drm_device *dev) I915_WRITE(VCLK_POST_DIV, dev_priv->saveVCLK_POST_DIV); udelay(150); + /* Clock gating state */ + I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D); + + /* Cache mode state */ + I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); + + /* Memory arbitration state */ + I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000); + for (i = 0; i < 16; i++) { I915_WRITE(SWF0 + (i << 2), dev_priv->saveSWF0[i]); I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]); diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 76116df..4d3ac0a 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -223,6 +223,9 @@ typedef struct drm_i915_private { u32 saveIER; u32 saveIIR; u32 saveIMR; + u32 saveCACHE_MODE_0; + u32 saveDSPCLK_GATE_D; + u32 saveMI_ARB_STATE; u32 saveSWF0[16]; u32 saveSWF1[16]; u32 saveSWF2[3]; @@ -576,6 +579,10 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); */ #define DMA_FADD_S 0x20d4 +/* Memory Interface Arbitration State + */ +#define MI_ARB_STATE 0x20e4 + /* Cache mode 0 reg. * - Manipulating render cache behaviour is central * to the concept of zone rendering, tuning this reg can help avoid @@ -586,6 +593,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); * bit of interest either set or cleared. EG: (BIT<<16) | BIT to set. */ #define Cache_Mode_0 0x2120 +#define CACHE_MODE_0 0x2120 #define CM0_MASK_SHIFT 16 #define CM0_IZ_OPT_DISABLE (1<<6) #define CM0_ZR_OPT_DISABLE (1<<5) @@ -775,6 +783,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); /** P1 value is 2 greater than this field */ # define VGA0_PD_P1_MASK (0x1f << 0) +#define DSPCLK_GATE_D 0x6200 + /* I830 CRTC registers */ #define HTOTAL_A 0x60000 #define HBLANK_A 0x60004 commit cd87e6352bf529ae0bc57e8434ddfccec3660d9a Author: Stephane Marchesin <mar...@ic...> Date: Sat Feb 16 03:50:10 2008 +0100 nouveau: no GART on ia64 either. diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c index f4e641b..3d376ae 100644 --- a/shared-core/nouveau_mem.c +++ b/shared-core/nouveau_mem.c @@ -393,7 +393,7 @@ nouveau_mem_init_ttm(struct drm_device *dev) } /* GART */ -#ifndef __powerpc__ +#if !defined(__powerpc__) && !defined(__ia64__) if (drm_device_is_agp(dev) && dev->agp) { if ((ret = nouveau_mem_init_agp(dev, 1))) DRM_ERROR("Error initialising AGP: %d\n", ret); @@ -462,7 +462,7 @@ int nouveau_mem_init(struct drm_device *dev) dev_priv->fb_nomap_heap=NULL; } -#ifndef __powerpc__ +#if !defined(__powerpc__) && !defined(__ia64__) /* Init AGP / NV50 PCIEGART */ if (drm_device_is_agp(dev) && dev->agp) { if ((ret = nouveau_mem_init_agp(dev, 0))) commit 15cbde683f5006b541b22c41ff840aefb017ff8e Author: Ben Skeggs <sk...@gm...> Date: Sat Feb 16 04:33:27 2008 +1100 nv40: actually init all tile regs. diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index 283977b..2f7d77c 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -335,19 +335,19 @@ #define NV04_PGRAPH_BLEND 0x00400824 #define NV04_PGRAPH_STORED_FMT 0x00400830 #define NV04_PGRAPH_PATT_COLORRAM 0x00400900 -#define NV40_PGRAPH_TILE0(i) 0x00400900 -#define NV40_PGRAPH_TLIMIT0(i) 0x00400904 -#define NV40_PGRAPH_TSIZE0(i) 0x00400908 -#define NV40_PGRAPH_TSTATUS0(i) 0x0040090C +#define NV40_PGRAPH_TILE0(i) (0x00400900 + (i*16)) +#define NV40_PGRAPH_TLIMIT0(i) (0x00400904 + (i*16)) +#define NV40_PGRAPH_TSIZE0(i) (0x00400908 + (i*16)) +#define NV40_PGRAPH_TSTATUS0(i) (0x0040090C + (i*16)) #define NV10_PGRAPH_TILE(i) (0x00400B00 + (i*16)) #define NV10_PGRAPH_TLIMIT(i) (0x00400B04 + (i*16)) #define NV10_PGRAPH_TSIZE(i) (0x00400B08 + (i*16)) #define NV10_PGRAPH_TSTATUS(i) (0x00400B0C + (i*16)) #define NV04_PGRAPH_U_RAM 0x00400D00 -#define NV47_PGRAPH_TILE0(i) 0x00400D00 -#define NV47_PGRAPH_TLIMIT0(i) 0x00400D04 -#define NV47_PGRAPH_TSIZE0(i) 0x00400D08 -#define NV47_PGRAPH_TSTATUS0(i) 0x00400D0C +#define NV47_PGRAPH_TILE0(i) (0x00400D00 + (i*16)) +#define NV47_PGRAPH_TLIMIT0(i) (0x00400D04 + (i*16)) +#define NV47_PGRAPH_TSIZE0(i) (0x00400D08 + (i*16)) +#define NV47_PGRAPH_TSTATUS0(i) (0x00400D0C + (i*16)) #define NV04_PGRAPH_V_RAM 0x00400D40 #define NV04_PGRAPH_W_RAM 0x00400D80 #define NV10_PGRAPH_COMBINER0_IN_ALPHA 0x00400E40 @@ -395,10 +395,10 @@ #define NV04_PGRAPH_DMA_B_OFFSET 0x00401098 #define NV04_PGRAPH_DMA_B_SIZE 0x0040109C #define NV04_PGRAPH_DMA_B_Y_SIZE 0x004010A0 -#define NV40_PGRAPH_TILE1(i) 0x00406900 -#define NV40_PGRAPH_TLIMIT1(i) 0x00406904 -#define NV40_PGRAPH_TSIZE1(i) 0x00406908 -#define NV40_PGRAPH_TSTATUS1(i) 0x0040690C +#define NV40_PGRAPH_TILE1(i) (0x00406900 + (i*16)) +#define NV40_PGRAPH_TLIMIT1(i) (0x00406904 + (i*16)) +#define NV40_PGRAPH_TSIZE1(i) (0x00406908 + (i*16)) +#define NV40_PGRAPH_TSTATUS1(i) (0x0040690C + (i*16)) /* It's a guess that this works on NV03. Confirmed on NV04, though */ commit 373dbcf8b25750967e9ba24433cff872df41cb74 Author: Kristian Høgsberg <kr...@re...> Date: Tue Feb 5 13:27:16 2008 -0500 i915: Add a dri2 init path that gets the lock from the dri2 sarea. diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index fc00920..3874ed5 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -106,9 +106,73 @@ static int i915_dma_cleanup(struct drm_device * dev) return 0; } -static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) + +#define DRI2_SAREA_BLOCK_TYPE(b) ((b) >> 16) +#define DRI2_SAREA_BLOCK_SIZE(b) ((b) & 0xffff) +#define DRI2_SAREA_BLOCK_NEXT(p) \ + ((void *) ((unsigned char *) (p) + \ + DRI2_SAREA_BLOCK_SIZE(*(unsigned int *) p))) + +#define DRI2_SAREA_BLOCK_END 0x0000 +#define DRI2_SAREA_BLOCK_LOCK 0x0001 +#define DRI2_SAREA_BLOCK_EVENT_BUFFER 0x0002 + +static int +setup_dri2_sarea(struct drm_device * dev, + struct drm_file *file_priv, + drm_i915_init_t * init) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + int ret; + unsigned int *p, *end, *next; + + mutex_lock(&dev->struct_mutex); + dev_priv->sarea_bo = + drm_lookup_buffer_object(file_priv, + init->sarea_handle, 1); + mutex_unlock(&dev->struct_mutex); + + if (!dev_priv->sarea_bo) { + DRM_ERROR("did not find sarea bo\n"); + return -EINVAL; + } + + ret = drm_bo_kmap(dev_priv->sarea_bo, 0, + dev_priv->sarea_bo->num_pages, + &dev_priv->sarea_kmap); + if (ret) { + DRM_ERROR("could not map sarea bo\n"); + return ret; + } + + p = dev_priv->sarea_kmap.virtual; + end = (void *) p + (dev_priv->sarea_bo->num_pages << PAGE_SHIFT); + while (p < end && DRI2_SAREA_BLOCK_TYPE(*p) != DRI2_SAREA_BLOCK_END) { + switch (DRI2_SAREA_BLOCK_TYPE(*p)) { + case DRI2_SAREA_BLOCK_LOCK: + dev->lock.hw_lock = (void *) (p + 1); + dev->sigdata.lock = dev->lock.hw_lock; + break; + } + next = DRI2_SAREA_BLOCK_NEXT(p); + if (next <= p || end < next) { + DRM_ERROR("malformed dri2 sarea: next is %p should be within %p-%p\n", + next, p, end); + return -EINVAL; + } + p = next; + } + + return 0; +} + + +static int i915_initialize(struct drm_device * dev, + struct drm_file *file_priv, + drm_i915_init_t * init) { drm_i915_private_t *dev_priv = dev->dev_private; + int ret; dev_priv->sarea = drm_getsarea(dev); if (!dev_priv->sarea) { @@ -201,6 +265,17 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) #ifdef I915_HAVE_BUFFER mutex_init(&dev_priv->cmdbuf_mutex); #endif + + if (init->func == I915_INIT_DMA2) { + ret = setup_dri2_sarea(dev, file_priv, init); + if (ret) { + i915_dma_cleanup(dev); + DRM_ERROR("could not set up dri2 sarea\n"); + return ret; + } + } + + return 0; } @@ -250,7 +325,8 @@ static int i915_dma_init(struct drm_device *dev, void *data, switch (init->func) { case I915_INIT_DMA: - retcode = i915_initialize(dev, init); + case I915_INIT_DMA2: + retcode = i915_initialize(dev, file_priv, init); break; case I915_CLEANUP_DMA: retcode = i915_dma_cleanup(dev); @@ -1415,6 +1491,20 @@ void i915_driver_lastclose(struct drm_device * dev) if (dev_priv->agp_heap) i915_mem_takedown(&(dev_priv->agp_heap)); + if (dev_priv->sarea_kmap.virtual) { + drm_bo_kunmap(&dev_priv->sarea_kmap); + dev_priv->sarea_kmap.virtual = NULL; + dev->lock.hw_lock = NULL; + dev->sigdata.lock = NULL; + } + + if (dev_priv->sarea_bo) { + mutex_lock(&dev->struct_mutex); + drm_bo_usage_deref_locked(&dev_priv->sarea_bo); + mutex_unlock(&dev->struct_mutex); + dev_priv->sarea_bo = NULL; + } + i915_dma_cleanup(dev); } diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index ad0797c..b889a30 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -43,7 +43,12 @@ typedef struct _drm_i915_init { enum { I915_INIT_DMA = 0x01, I915_CLEANUP_DMA = 0x02, - I915_RESUME_DMA = 0x03 + I915_RESUME_DMA = 0x03, + + /* Since this struct isn't versioned, just used a new + * 'func' code to indicate the presence of dri2 sarea + * info. */ + I915_INIT_DMA2 = 0x04 } func; unsigned int mmio_offset; int sarea_priv_offset; @@ -61,6 +66,7 @@ typedef struct _drm_i915_init { unsigned int depth_pitch; unsigned int cpp; unsigned int chipset; + unsigned int sarea_handle; } drm_i915_init_t; typedef struct _drm_i915_sarea { diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index d08fdf4..76116df 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -147,6 +147,10 @@ typedef struct drm_i915_private { drm_i915_vbl_swap_t vbl_swaps; unsigned int swaps_pending; + /* DRI2 sarea */ + struct drm_buffer_object *sarea_bo; + struct drm_bo_kmap_obj sarea_kmap; + /* Register state */ u8 saveLBB; u32 saveDSPACNTR; commit db3f03ae3538bea3d29ef66ac24d9a1f54cff418 Author: Kristian Høgsberg <kr...@re...> Date: Tue Feb 12 16:08:18 2008 -0500 i915: Only look up dev_priv->mmio_map if it's not already set up diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 0682a33..fc00920 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -117,7 +117,8 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) return -EINVAL; } - dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset); + if (init->mmio_offset != 0) + dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset); if (!dev_priv->mmio_map) { i915_dma_cleanup(dev); DRM_ERROR("can not find mmio map!\n"); commit ee15459483d50b2efe630051b45f36cfbb351683 Author: Kristian Høgsberg <kr...@re...> Date: Tue Feb 5 12:27:48 2008 -0500 i915: Add I915_PARAM_CHIPSET_ID param to get chipset ID. diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 9619525..0682a33 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1210,6 +1210,9 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_LAST_DISPATCH: value = READ_BREADCRUMB(dev_priv); break; + case I915_PARAM_CHIPSET_ID: + value = dev->pci_device; + break; default: DRM_ERROR("Unknown parameter %d\n", param->param); return -EINVAL; diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index c8a9cb7..ad0797c 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -232,6 +232,7 @@ typedef struct drm_i915_irq_wait { #define I915_PARAM_IRQ_ACTIVE 1 #define I915_PARAM_ALLOW_BATCHBUFFER 2 #define I915_PARAM_LAST_DISPATCH 3 +#define I915_PARAM_CHIPSET_ID 4 typedef struct drm_i915_getparam { int param; commit 4feb0638f1a8eb8527647ff47312ee61e3f683f9 Author: Kristian Høgsberg <kr...@re...> Date: Tue Feb 5 12:25:22 2008 -0500 i915: Make sarea_priv setup optional. diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 608723f..9619525 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -128,8 +128,14 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) dev_priv->max_validate_buffers = I915_MAX_VALIDATE_BUFFERS; #endif - dev_priv->sarea_priv = (drm_i915_sarea_t *) - ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset); + if (init->sarea_priv_offset) + dev_priv->sarea_priv = (drm_i915_sarea_t *) + ((u8 *) dev_priv->sarea->handle + + init->sarea_priv_offset); + else { + /* No sarea_priv for you! */ + dev_priv->sarea_priv = NULL; + } dev_priv->ring.Start = init->ring_start; dev_priv->ring.End = init->ring_end; @@ -154,7 +160,9 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) dev_priv->ring.virtual_start = dev_priv->ring.map.handle; dev_priv->cpp = init->cpp; - dev_priv->sarea_priv->pf_current_page = 0; + + if (dev_priv->sarea_priv) + dev_priv->sarea_priv->pf_current_page = 0; /* We are using separate values as placeholders for mechanisms for * private backbuffer/depthbuffer usage. @@ -426,7 +434,8 @@ void i915_emit_breadcrumb(struct drm_device *dev) DRM_DEBUG("Breadcrumb counter wrapped around\n"); } - dev_priv->sarea_priv->last_enqueue = dev_priv->counter; + if (dev_priv->sarea_priv) + dev_priv->sarea_priv->last_enqueue = dev_priv->counter; BEGIN_LP_RING(4); OUT_RING(CMD_STORE_DWORD_IDX); @@ -1101,7 +1110,8 @@ static int i915_execbuffer(struct drm_device *dev, void *data, if (ret) goto out_err0; - sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + if (sarea_priv) + sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); /* fence */ ret = drm_fence_buffer_objects(dev, NULL, fence_arg->flags, diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index d463f6e..fd08b6e 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -450,7 +450,9 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG); - dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + if (dev_priv->sarea_priv) + dev_priv->sarea_priv->last_dispatch = + READ_BREADCRUMB(dev_priv); if (temp & USER_INT_FLAG) { DRM_WAKEUP(&dev_priv->irq_queue); @@ -529,7 +531,9 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) READ_BREADCRUMB(dev_priv), (int)dev_priv->counter); } - dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + if (dev_priv->sarea_priv) + dev_priv->sarea_priv->last_dispatch = + READ_BREADCRUMB(dev_priv); return ret; } @@ -693,7 +697,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data, return -EINVAL; } - if (dev_priv->sarea_priv->rotation) { + if (!dev_priv->sarea_priv || dev_priv->sarea_priv->rotation) { DRM_DEBUG("Rotation not supported\n"); return -EINVAL; } commit d63b57749f097b36df04c6beff9b35a1dd859523 Author: Jesse Barnes <jb...@ho...> Date: Thu Feb 7 17:33:28 2008 -0800 Restore pipeconf regs unconditionally On many chipsets, the checks for DPLL enable or VGA mode will prevent the pipeconf regs from being restored, which could result in a blank display or X failing to come back after resume. So restore them unconditionally along with actually restoring pipe B's palette correctly. diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index c771ab3..3e2bfc9 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -434,9 +434,7 @@ static int i915_resume(struct drm_device *dev) I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); } - if ((dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) && - (dev_priv->saveDPLL_A & DPLL_VGA_MODE_DIS)) - I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF); + I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF); i915_restore_palette(dev, PIPE_A); /* Enable the plane */ @@ -478,10 +476,9 @@ static int i915_resume(struct drm_device *dev) I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); } - if ((dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) && - (dev_priv->saveDPLL_B & DPLL_VGA_MODE_DIS)) - I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); - i915_restore_palette(dev, PIPE_A); + I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); + + i915_restore_palette(dev, PIPE_B); /* Enable the plane */ I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); I915_WRITE(DSPBBASE, I915_READ(DSPBBASE)); commit 6f19473191ae543fcc199d252c5865c0734d38ad Author: Jesse Barnes <jb...@ni...> Date: Thu Feb 7 11:21:09 2008 -0800 Fix saveGR array size Make sure we have enough room for all the GR registers or we'll end up clobbering the AR index register (which should actually be harmless unless the BIOS is making an assumption about it). diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index d2faee2..d08fdf4 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -224,7 +224,7 @@ typedef struct drm_i915_private { u32 saveSWF2[3]; u8 saveMSR; u8 saveSR[8]; - u8 saveGR[24]; + u8 saveGR[25]; u8 saveAR_INDEX; u8 saveAR[20]; u8 saveDACMASK; commit 8b6c96dedd4ba5dfbfec6a7c831d566e31d28781 Author: Jesse Barnes <jb...@ni...> Date: Thu Feb 7 10:48:08 2008 -0800 i915: save/restore interrupt state On resume, if the interrupt state isn't restored correctly, we may end up with a flood of unexpected or ill-timed interrupts, which could cause the kernel to disable the interrupt or vblank events to happen at the wrong time. So save/restore them properly. diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index ccc061d..c771ab3 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -303,6 +303,7 @@ static int i915_suspend(struct drm_device *dev) dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF); } i915_save_palette(dev, PIPE_A); + dev_priv->savePIPEASTAT = I915_READ(I915REG_PIPEASTAT); /* Pipe & plane B info */ dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF); @@ -330,6 +331,7 @@ static int i915_suspend(struct drm_device *dev) dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF); } i915_save_palette(dev, PIPE_B); + dev_priv->savePIPEBSTAT = I915_READ(I915REG_PIPEBSTAT); /* CRT state */ dev_priv->saveADPA = I915_READ(ADPA); @@ -356,6 +358,11 @@ static int i915_suspend(struct drm_device *dev) dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2); dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL); + /* Interrupt state */ + dev_priv->saveIIR = I915_READ(I915REG_INT_IDENTITY_R); + dev_priv->saveIER = I915_READ(I915REG_INT_ENABLE_R); + dev_priv->saveIMR = I915_READ(I915REG_INT_MASK_R); + /* VGA state */ dev_priv->saveVCLK_DIVISOR_VGA0 = I915_READ(VCLK_DIVISOR_VGA0); dev_priv->saveVCLK_DIVISOR_VGA1 = I915_READ(VCLK_DIVISOR_VGA1); diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 8759467..d2faee2 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -166,6 +166,7 @@ typedef struct drm_i915_private { u32 saveVBLANK_A; u32 saveVSYNC_A; u32 saveBCLRPAT_A; + u32 savePIPEASTAT; u32 saveDSPASTRIDE; u32 saveDSPASIZE; u32 saveDSPAPOS; @@ -186,6 +187,7 @@ typedef struct drm_i915_private { u32 saveVBLANK_B; u32 saveVSYNC_B; u32 saveBCLRPAT_B; + u32 savePIPEBSTAT; u32 saveDSPBSTRIDE; u32 saveDSPBSIZE; u32 saveDSPBPOS; @@ -214,6 +216,9 @@ typedef struct drm_i915_private { u32 saveFBC_LL_BASE; u32 saveFBC_CONTROL; u32 saveFBC_CONTROL2; + u32 saveIER; + u32 saveIIR; + u32 saveIMR; u32 saveSWF0[16]; u32 saveSWF1[16]; u32 saveSWF2[3]; commit 79d69285202b55f269aa88a6bcda257257c9dee3 Author: Jesse Barnes <jb...@ni...> Date: Thu Feb 7 10:40:06 2008 -0800 Fix vblank enable/disable callbacks There were two problems with the existing callback code: the vblank enable callback happened multiple times per disable, making drivers more complex than they had to be, and there was a race between the final decrement of the vblank usage counter and the next enable call, which could have resulted in a put->schedule disable->get->enable->disable sequence, which would be bad. So add a new vblank_enabled array to track vblank enable on per-pipe basis, and add a lock to protect it along with the refcount + enable/disable calls to fix the race. diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 4e8b087..33f3649 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -836,6 +836,8 @@ struct drm_device { u32 *last_vblank; /* protected by dev->vbl_lock, used */ /* for wraparound handling */ u32 *vblank_offset; /* used to track how many vblanks */ + int *vblank_enabled; /* so we don't call enable more than + once per disable */ u32 *vblank_premodeset; /* were lost during modeset */ struct timer_list vblank_disable_timer; diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index 367d2dd..e4940bb 100644 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@ -74,11 +74,18 @@ int drm_irq_by_busid(struct drm_device *dev, void *data, static void vblank_disable_fn(unsigned long arg) { struct drm_device *dev = (struct drm_device *)arg; + unsigned long irqflags; int i; - for (i = 0; i < dev->num_crtcs; i++) - if (atomic_read(&dev->vblank_refcount[i]) == 0) + for (i = 0; i < dev->num_crtcs; i++) { + spin_lock_irqsave(&dev->vbl_lock, irqflags); + if (atomic_read(&dev->vblank_refcount[i]) == 0 && + dev->vblank_enabled[i]) { dev->driver->disable_vblank(dev, i); + dev->vblank_enabled[i] = 0; + } + spin_unlock_irqrestore(&dev->vbl_lock, irqflags); + } } int drm_vblank_init(struct drm_device *dev, int num_crtcs) @@ -111,6 +118,11 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) if (!dev->vblank_refcount) goto err; + dev->vblank_enabled = drm_calloc(num_crtcs, sizeof(int), + DRM_MEM_DRIVER); + if (!dev->vblank_enabled) + goto err; + dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER); if (!dev->last_vblank) goto err; @@ -143,6 +155,8 @@ err: DRM_MEM_DRIVER); drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) * num_crtcs, DRM_MEM_DRIVER); + drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) * num_crtcs, + DRM_MEM_DRIVER); drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * num_crtcs, DRM_MEM_DRIVER); drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) * @@ -357,14 +371,20 @@ EXPORT_SYMBOL(drm_update_vblank_count); */ int drm_vblank_get(struct drm_device *dev, int crtc) { + unsigned long irqflags; int ret = 0; + spin_lock_irqsave(&dev->vbl_lock, irqflags); /* Going from 0->1 means we have to enable interrupts again */ - if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) { + if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 && + !dev->vblank_enabled[crtc]) { ret = dev->driver->enable_vblank(dev, crtc); if (ret) atomic_dec(&dev->vblank_refcount[crtc]); + else + dev->vblank_enabled[crtc] = 1; } + spin_unlock_irqrestore(&dev->vbl_lock, irqflags); return ret; } @@ -382,8 +402,7 @@ void drm_vblank_put(struct drm_device *dev, int crtc) { /* Last user schedules interrupt disable */ if (atomic_dec_and_test(&dev->vblank_refcount[crtc])) - mod_timer(&dev->vblank_disable_timer, - round_jiffies_relative(DRM_HZ)); + mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ); } EXPORT_SYMBOL(drm_vblank_put); commit 76748efae2f51409813eeb6b91b783c73cb2845e Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> Date: Tue Feb 5 10:35:56 2008 +0100 i915: Re-report breadcrumbs on poll to the fence manager, since a breadcrumb may actually turn up before a corresponding fence object has been placed on the fence ring. diff --git a/linux-core/i915_fence.c b/linux-core/i915_fence.c index 8a2e7f1..de64a4f 100644 --- a/linux-core/i915_fence.c +++ b/linux-core/i915_fence.c @@ -38,10 +38,10 @@ * Initiate a sync flush if it's not already pending. */ -static void i915_initiate_rwflush(struct drm_i915_private *dev_priv, - struct drm_fence_class_manager *fc) +static inline void i915_initiate_rwflush(struct drm_i915_private *dev_priv, + struct drm_fence_class_manager *fc) { - if ((fc->pending_flush & DRM_I915_FENCE_TYPE_RW) && + if ((fc->pending_flush & DRM_I915_FENCE_TYPE_RW) && !dev_priv->flush_pending) { dev_priv->flush_sequence = (uint32_t) READ_BREADCRUMB(dev_priv); dev_priv->flush_flags = fc->pending_flush; @@ -52,6 +52,27 @@ static void i915_initiate_rwflush(struct drm_i915_private *dev_priv, } } +static inline void i915_report_rwflush(struct drm_device *dev, + struct drm_i915_private *dev_priv) +{ + if (unlikely(dev_priv->flush_pending)) { + + uint32_t flush_flags; + uint32_t i_status; + uint32_t flush_sequence; + + 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, 0, flush_sequence, + flush_flags, 0); + } + } +} + static void i915_fence_flush(struct drm_device *dev, uint32_t fence_class) { @@ -69,15 +90,13 @@ static void i915_fence_flush(struct drm_device *dev, write_unlock_irqrestore(&fm->lock, irq_flags); } + static void i915_fence_poll(struct drm_device *dev, uint32_t fence_class, uint32_t waiting_types) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; struct drm_fence_manager *fm = &dev->fm; struct drm_fence_class_manager *fc = &fm->fence_class[0]; - uint32_t flush_flags = 0; - uint32_t flush_sequence = 0; - uint32_t i_status; uint32_t sequence; if (unlikely(!dev_priv)) @@ -87,36 +106,24 @@ static void i915_fence_poll(struct drm_device *dev, uint32_t fence_class, * First, report any executed sync flush: */ - 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, 0, flush_sequence, flush_flags, 0); - } - } + i915_report_rwflush(dev, dev_priv); /* * Report A new breadcrumb, and adjust IRQs. */ if (waiting_types & DRM_FENCE_TYPE_EXE) { - sequence = READ_BREADCRUMB(dev_priv); - if (sequence != dev_priv->reported_sequence || - !dev_priv->reported_sequence_valid) { - drm_fence_handler(dev, 0, sequence, - DRM_FENCE_TYPE_EXE, 0); - dev_priv->reported_sequence = sequence; - dev_priv->reported_sequence_valid = 1; - } + sequence = READ_BREADCRUMB(dev_priv); + drm_fence_handler(dev, 0, sequence, + DRM_FENCE_TYPE_EXE, 0); - if (dev_priv->fence_irq_on && !(waiting_types & DRM_FENCE_TYPE_EXE)) { + if (dev_priv->fence_irq_on && + !(fc->waiting_types & DRM_FENCE_TYPE_EXE)) { i915_user_irq_off(dev_priv); dev_priv->fence_irq_on = 0; - } else if (!dev_priv->fence_irq_on && (waiting_types & DRM_FENCE_TYPE_EXE)) { + } else if (!dev_priv->fence_irq_on && + (fc->waiting_types & DRM_FENCE_TYPE_EXE)) { i915_user_irq_on(dev_priv); dev_priv->fence_irq_on = 1; } @@ -129,19 +136,11 @@ static void i915_fence_poll(struct drm_device *dev, uint32_t fence_class, i915_initiate_rwflush(dev_priv, fc); /* - * And possibly, but unlikely, they finish immediately. + * And possibly, but unlikely, they finish immediately. */ - if (dev_priv->flush_pending) { - i_status = READ_HWSP(dev_priv, 0); - if (unlikely((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, 0, flush_sequence, flush_flags, 0); - } - } + i915_report_rwflush(dev, dev_priv); + } static int i915_fence_emit_sequence(struct drm_device *dev, uint32_t class, @@ -258,27 +257,6 @@ static uint32_t i915_fence_needed_flush(struct drm_fence_object *fence) return flush_flags; } -/* - * In the very unlikely event that "poll" is not really called very often - * we need the following function to handle sequence wraparounds. - */ - -void i915_invalidate_reported_sequence(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = (struct drm_i915_private *) - dev->dev_private; - struct drm_fence_manager *fm = &dev->fm; - unsigned long irq_flags; - - if (unlikely(!dev_priv)) - return; - - write_lock_irqsave(&fm->lock, irq_flags); - dev_priv->reported_sequence_valid = 0; - write_unlock_irqrestore(&fm->lock, irq_flags); -} - - struct drm_fence_driver i915_fence_driver = { .num_classes = 1, .wrap_diff = (1U << (BREADCRUMB_BITS - 1)), diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index a012f68..608723f 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -422,9 +422,6 @@ void i915_emit_breadcrumb(struct drm_device *dev) RING_LOCALS; if (++dev_priv->counter > BREADCRUMB_MASK) { -#ifdef I915_HAVE_FENCE - i915_invalidate_reported_sequence(dev); -#endif dev_priv->counter = 1; DRM_DEBUG("Breadcrumb counter wrapped around\n"); } diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 3f6c806..8759467 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -136,8 +136,6 @@ typedef struct drm_i915_private { uint32_t flush_flags; uint32_t flush_pending; uint32_t saved_flush_status; - uint32_t reported_sequence; - int reported_sequence_valid; #endif #ifdef I915_HAVE_BUFFER void *agp_iomap; commit a0781e762295ce3d5f6e839d437a0de505cefa3b Author: Stuart Bennett <sb...@ca...> Date: Mon Jan 28 22:59:26 2008 +0000 nouveau: make nv34 work every time, not just every 2nd time And make nv30_graph_init a bit more like mmio-traces diff --git a/shared-core/nv20_graph.c b/shared-core/nv20_graph.c index 37a147b..ad73ea9 100644 --- a/shared-core/nv20_graph.c +++ b/shared-core/nv20_graph.c @@ -804,7 +804,7 @@ void nv20_graph_takedown(struct drm_device *dev) int nv30_graph_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t vramsz, tmp; +// uint32_t vramsz, tmp; int ret, i; NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) & @@ -834,6 +834,7 @@ int nv30_graph_init(struct drm_device *dev) NV_WRITE(NV10_PGRAPH_DEBUG_4, 0x00008000); NV_WRITE(NV04_PGRAPH_LIMIT_VIOL_PIX, 0xf04bdff6); NV_WRITE(0x400B80, 0x1003d888); + NV_WRITE(0x400B84, 0x0c000000); NV_WRITE(0x400098, 0x00000000); NV_WRITE(0x40009C, 0x0005ad00); NV_WRITE(0x400B88, 0x62ff00ff); // suspiciously like PGRAPH_DEBUG_2 @@ -843,30 +844,47 @@ int nv30_graph_init(struct drm_device *dev) NV_WRITE(0x400ba0, 0x002f8685); NV_WRITE(0x400ba4, 0x00231f3f); NV_WRITE(0x4008a4, 0x40000020); - NV_WRITE(0x400B84, 0x0c000000); - NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x62ff0f7f); + + if (dev_priv->chipset == 0x34) { + NV_WRITE(NV10_PGRAPH_RDI_INDEX, 0x00EA0004); + NV_WRITE(NV10_PGRAPH_RDI_DATA , 0x00200201); + NV_WRITE(NV10_PGRAPH_RDI_INDEX, 0x00EA0008); + NV_WRITE(NV10_PGRAPH_RDI_DATA , 0x00000008); + NV_WRITE(NV10_PGRAPH_RDI_INDEX, 0x00EA0000); + NV_WRITE(NV10_PGRAPH_RDI_DATA , 0x00000032); + NV_WRITE(NV10_PGRAPH_RDI_INDEX, 0x00E00004); + NV_WRITE(NV10_PGRAPH_RDI_DATA , 0x00000002); + } + NV_WRITE(0x4000c0, 0x00000016); /* copy tile info from PFB */ - for (i=0; i<NV10_PFB_TILE__SIZE; i++) { - NV_WRITE(NV10_PGRAPH_TILE(i), NV_READ(NV10_PFB_TILE(i))); - NV_WRITE(NV10_PGRAPH_TLIMIT(i), NV_READ(NV10_PFB_TLIMIT(i))); - NV_WRITE(NV10_PGRAPH_TSIZE(i), NV_READ(NV10_PFB_TSIZE(i))); - NV_WRITE(NV10_PGRAPH_TSTATUS(i), NV_READ(NV10_PFB_TSTATUS(i))); + for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { + NV_WRITE(0x00400904 + i*0x10, NV_READ(NV10_PFB_TLIMIT(i))); + /* which is NV40_PGRAPH_TLIMIT0(i) ?? */ + NV_WRITE(0x00400908 + i*0x10, NV_READ(NV10_PFB_TSIZE(i))); + /* which is NV40_PGRAPH_TSIZE0(i) ?? */ + NV_WRITE(0x00400900 + i*0x10, NV_READ(NV10_PFB_TILE(i))); + /* which is NV40_PGRAPH_TILE0(i) ?? */ } NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10000100); NV_WRITE(NV10_PGRAPH_STATE , 0xFFFFFFFF); + NV_WRITE(0x0040075c , 0x00000001); NV_WRITE(NV04_PGRAPH_FIFO , 0x00000001); /* begin RAM config */ - vramsz = drm_get_resource_len(dev, 0) - 1; +// vramsz = drm_get_resource_len(dev, 0) - 1; NV_WRITE(0x4009A4, NV_READ(NV04_PFB_CFG0)); NV_WRITE(0x4009A8, NV_READ(NV04_PFB_CFG1)); - NV_WRITE(0x400750, 0x00EA0000); - NV_WRITE(0x400754, NV_READ(NV04_PFB_CFG0)); - NV_WRITE(0x400750, 0x00EA0004); - NV_WRITE(0x400754, NV_READ(NV04_PFB_CFG1)); + if (dev_priv->chipset != 0x34) { + NV_WRITE(0x400750, 0x00EA0000); + NV_WRITE(0x400754, NV_READ(NV04_PFB_CFG0)); + NV_WRITE(0x400750, 0x00EA0004); + NV_WRITE(0x400754, NV_READ(NV04_PFB_CFG1)); + } + +#if 0 NV_WRITE(0x400820, 0); NV_WRITE(0x400824, 0); NV_WRITE(0x400864, vramsz-1); @@ -885,6 +903,7 @@ int nv30_graph_init(struct drm_device *dev) NV_WRITE(NV03_PGRAPH_ABS_UCLIP_YMIN, 0); NV_WRITE(NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff); NV_WRITE(NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff); +#endif return 0; } commit 733e07663e50087ca1e9af8e9b5def556521e3b5 Author: Maarten Maathuis <mad...@gm...> Date: Sat Feb 2 12:46:31 2008 +0100 nouveau: NV40 can/should now be able to run after the blob. - Moved the fix from the ddx to drm, because it seemed more appropriate. - Don't be shy, report if it works for you or not. diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index a250614..283977b 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -138,6 +138,7 @@ #define NV40_PFB_TLIMIT(i) (0x00100604 + (i*16)) #define NV40_PFB_TSIZE(i) (0x00100608 + (i*16)) #define NV40_PFB_TSTATUS(i) (0x0010060C + (i*16)) +#define NV40_PFB_UNK_800 0x00100800 #define NV04_PGRAPH_DEBUG_0 0x00400080 #define NV04_PGRAPH_DEBUG_1 0x00400084 diff --git a/shared-core/nv40_fb.c b/shared-core/nv40_fb.c index ceae807..ae784cb 100644 --- a/shared-core/nv40_fb.c +++ b/shared-core/nv40_fb.c @@ -11,6 +11,13 @@ nv40_fb_init(struct drm_device *dev) int num_tiles; int i; + /* This is strictly a NV4x register (don't know about NV5x). */ + /* The blob sets these to all kinds of values, and they mess up our setup. */ + /* I got value 0x52802 instead. For some cards the blob even sets it back to 0x1. */ + /* Note: the blob doesn't read this value, so i'm pretty sure this is safe for all cards. */ + /* Any idea what this is? */ + NV_WRITE(NV40_PFB_UNK_800, 0x1); + switch (dev_priv->chipset) { case 0x40: case 0x45: commit c77b0937f290568604961fa0013691349c5fcf3b Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> Date: Thu Jan 31 14:11:12 2008 +0100 Add an fence_class_manager::last_queued_sequence member, since a sequence number may actually turn up before the corresponding fence object has been queued on the ring. Fence drivers can use this member to determine whether a sequence number must be re-reported. diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index a852c63..247bc0a 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -129,8 +129,8 @@ void drm_fence_handler(struct drm_device *dev, uint32_t fence_class, type |= fence->native_types; relevant_type = type & fence->type; - new_type = (fence->signaled_types | relevant_type) & - ~fence->signaled_types; + new_type = (fence->signaled_types | relevant_type) ^ + fence->signaled_types; if (new_type) { fence->signaled_types |= new_type; @@ -450,6 +450,7 @@ int drm_fence_object_emit(struct drm_fence_object *fence, uint32_t fence_flags, if (list_empty(&fc->ring)) fc->highest_waiting_sequence = sequence - 1; list_add_tail(&fence->ring, &fc->ring); + fc->latest_queued_sequence = sequence; write_unlock_irqrestore(&fm->lock, flags); return 0; } @@ -554,8 +555,8 @@ void drm_fence_manager_init(struct drm_device *dev) for (i = 0; i < fm->num_classes; ++i) { fence_class = &fm->fence_class[i]; + memset(fence_class, 0, sizeof(*fence_class)); INIT_LIST_HEAD(&fence_class->ring); - fence_class->pending_flush = 0; DRM_INIT_WAITQUEUE(&fence_class->fence_queue); } diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index c35d900..e43e8df 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -164,6 +164,7 @@ struct drm_fence_class_manager { uint32_t waiting_types; wait_queue_head_t fence_queue; uint32_t highest_waiting_sequence; + uint32_t latest_queued_sequence; }; struct drm_fence_manager { commit 47ee6237fe86a8621744bbd6cecb8b5e58848b05 Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> Date: Wed Jan 30 22:14:02 2008 +0100 i915: Avoid calling drm_fence_flush_old excessively. diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 15fb811..a012f68 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -494,7 +494,8 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev, i915_emit_breadcrumb(dev); #ifdef I915_HAVE_FENCE - drm_fence_flush_old(dev, 0, dev_priv->counter); + if (unlikely((dev_priv->counter & 0xFF) == 0)) + drm_fence_flush_old(dev, 0, dev_priv->counter); #endif return 0; } @@ -548,7 +549,8 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, i915_emit_breadcrumb(dev); #ifdef I915_HAVE_FENCE - drm_fence_flush_old(dev, 0, dev_priv->counter); + if (unlikely((dev_priv->counter & 0xFF) == 0)) + drm_fence_flush_old(dev, 0, dev_priv->counter); #endif return 0; } @@ -621,7 +623,7 @@ void i915_dispatch_flip(struct drm_device * dev, int planes, int sync) i915_emit_breadcrumb(dev); #ifdef I915_HAVE_FENCE - if (!sync) + if (unlikely(!sync && ((dev_priv->counter & 0xFF) == 0))) drm_fence_flush_old(dev, 0, dev_priv->counter); #endif } commit f1edb7ad91d8b92057ffa02eb162e3740d05a147 Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> Date: Wed Jan 30 22:06:02 2008 +0100 Simplify the fencing code and differentiate between flushes and waiting types. Add a "command_stream_barrier" method to the bo driver. diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index df10e12..3b180d1 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -287,7 +287,7 @@ int drm_bo_wait(struct drm_buffer_object *bo, int lazy, int ignore_signals, DRM_ASSERT_LOCKED(&bo->mutex); if (bo->fence) { - if (drm_fence_object_signaled(bo->fence, bo->fence_type, 0)) { + if (drm_fence_object_signaled(bo->fence, bo->fence_type)) { drm_fence_usage_deref_unlocked(&bo->fence); return 0; } @@ -354,7 +354,7 @@ static void drm_bo_cleanup_refs(struct drm_buffer_object *bo, int remove_all) DRM_FLAG_MASKED(bo->priv_flags, 0, _DRM_BO_FLAG_UNFENCED); if (bo->fence && drm_fence_object_signaled(bo->fence, - bo->fence_type, 0)) + bo->fence_type)) drm_fence_usage_deref_unlocked(&bo->fence); if (bo->fence && remove_all) @@ -559,7 +559,7 @@ void drm_putback_buffer_objects(struct drm_device *dev) list_del_init(&entry->lru); DRM_FLAG_MASKED(entry->priv_flags, 0, _DRM_BO_FLAG_UNFENCED); - DRM_WAKEUP(&entry->event_queue); + wake_up_all(&entry->event_queue); /* * FIXME: Might want to put back on head of list @@ -660,7 +660,7 @@ int drm_fence_buffer_objects(struct drm_device *dev, entry->fence_type = entry->new_fence_type; DRM_FLAG_MASKED(entry->priv_flags, 0, _DRM_BO_FLAG_UNFENCED); - DRM_WAKEUP(&entry->event_queue); + wake_up_all(&entry->event_queue); drm_bo_add_to_lru(entry); } mutex_unlock(&entry->mutex); @@ -1032,7 +1032,7 @@ static int drm_bo_quick_busy(struct drm_buffer_object *bo) BUG_ON(bo->priv_flags & _DRM_BO_FLAG_UNFENCED); if (fence) { - if (drm_fence_object_signaled(fence, bo->fence_type, 0)) { + if (drm_fence_object_signaled(fence, bo->fence_type)) { drm_fence_usage_deref_unlocked(&bo->fence); return 0; } @@ -1052,12 +1052,12 @@ static int drm_bo_busy(struct drm_buffer_object *bo) BUG_ON(bo->priv_flags & _DRM_BO_FLAG_UNFENCED); if (fence) { - if (drm_fence_object_signaled(fence, bo->fence_type, 0)) { + if (drm_fence_object_signaled(fence, bo->fence_type)) { drm_fence_usage_deref_unlocked(&bo->fence); return 0; } drm_fence_object_flush(fence, DRM_FENCE_TYPE_EXE); - if (drm_fence_object_signaled(fence, bo->fence_type, 0)) { + if (drm_fence_object_signaled(fence, bo->fence_type)) { drm_fence_usage_deref_unlocked(&bo->fence); return 0; } @@ -1249,7 +1249,7 @@ static int drm_buffer_object_map(struct drm_file *file_priv, uint32_t handle, mutex_unlock(&dev->struct_mutex); if (ret) { if (atomic_add_negative(-1, &bo->mapped)) - DRM_WAKEUP(&bo->event_queue); + wake_up_all(&bo->event_queue); } else drm_bo_fill_rep_arg(bo, rep); @@ -1306,7 +1306,7 @@ static void drm_buffer_user_object_unmap(struct drm_file *file_priv, BUG_ON(action != _DRM_REF_TYPE1); if (atomic_add_negative(-1, &bo->mapped)) - DRM_WAKEUP(&bo->event_queue); + wake_up_all(&bo->event_queue); } /* @@ -1364,7 +1364,7 @@ out_unlock: } drm_bo_add_to_lru(bo); if (bo->priv_flags & _DRM_BO_FLAG_UNFENCED) { - DRM_WAKEUP(&bo->event_queue); + wake_up_all(&bo->event_queue); DRM_FLAG_MASKED(bo->priv_flags, 0, _DRM_BO_FLAG_UNFENCED); } @@ -1442,13 +1442,21 @@ static int drm_buffer_object_validate(struct drm_buffer_object *bo, * We're switching command submission mechanism, * or cannot simply rely on the hardware serializing for us. * - * Wait for buffer idle. + * Insert a driver-dependant barrier or wait for buffer idle. */ if ((fence_class != bo->fence_class) || ((ftype ^ bo->fence_type) & bo->fence_type)) { - ret = drm_bo_wait(bo, 0, 0, no_wait); + ret = -EINVAL; + if (driver->command_stream_barrier) { + ret = driver->command_stream_barrier(bo, + fence_class, + ftype, + no_wait); + } + if (ret) + ret = drm_bo_wait(bo, 0, 0, no_wait); if (ret) return ret; @@ -1539,7 +1547,7 @@ static int drm_buffer_object_validate(struct drm_buffer_object *bo, } else { drm_bo_add_to_lru(bo); if (bo->priv_flags & _DRM_BO_FLAG_UNFENCED) { - DRM_WAKEUP(&bo->event_queue); + wake_up_all(&bo->event_queue); DRM_FLAG_MASKED(bo->priv_flags, 0, _DRM_BO_FLAG_UNFENCED); } diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index 288b4db..a852c63 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -30,6 +30,57 @@ #include "drmP.h" + +/* + * Convenience function to be called by fence::wait methods that + * need polling. + */ + +int drm_fence_wait_polling(struct drm_fence_object *fence, int lazy, + int interruptible, uint32_t mask, + unsigned long end_jiffies) +{ + struct drm_device *dev = fence->dev; + struct drm_fence_manager *fm = &dev->fm; + struct drm_fence_class_manager *fc = &fm->fence_class[fence->fence_class]; + uint32_t count = 0; + int ret; + + DECLARE_WAITQUEUE(entry, current); + add_wait_queue(&fc->fence_queue, &entr... [truncated message content] |