diff options
-rw-r--r-- | linux-core/drm_compat.c | 99 | ||||
-rw-r--r-- | linux-core/drm_compat.h | 3 | ||||
-rw-r--r-- | linux-core/drm_vm.c | 35 | ||||
-rw-r--r-- | linux-core/i915_drv.c | 4 | ||||
-rw-r--r-- | linux-core/i915_opregion.c | 2 | ||||
-rw-r--r-- | shared-core/i915_dma.c | 51 | ||||
-rw-r--r-- | shared-core/i915_drv.h | 1 | ||||
-rw-r--r-- | shared-core/i915_irq.c | 60 | ||||
-rw-r--r-- | shared-core/nouveau_fifo.c | 2 | ||||
-rw-r--r-- | shared-core/nv04_fifo.c | 4 | ||||
-rw-r--r-- | shared-core/nv40_graph.c | 10 | ||||
-rw-r--r-- | shared-core/r300_cmdbuf.c | 5 |
12 files changed, 199 insertions, 77 deletions
diff --git a/linux-core/drm_compat.c b/linux-core/drm_compat.c index 3d082e7e..c4ebc2fa 100644 --- a/linux-core/drm_compat.c +++ b/linux-core/drm_compat.c @@ -759,3 +759,102 @@ EXPORT_SYMBOL(kmap_atomic_prot_pfn); #endif +#ifdef DRM_FULL_MM_COMPAT +#ifdef DRM_NO_FAULT +unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, + unsigned long address) +{ + struct drm_buffer_object *bo = (struct drm_buffer_object *) vma->vm_private_data; + unsigned long page_offset; + struct page *page = NULL; + struct drm_ttm *ttm; + struct drm_device *dev; + unsigned long pfn; + int err; + unsigned long bus_base; + unsigned long bus_offset; + unsigned long bus_size; + unsigned long ret = NOPFN_REFAULT; + + if (address > vma->vm_end) + return NOPFN_SIGBUS; + + dev = bo->dev; + err = drm_bo_read_lock(&dev->bm.bm_lock, 1); + if (err) + return NOPFN_REFAULT; + + err = mutex_lock_interruptible(&bo->mutex); + if (err) { + drm_bo_read_unlock(&dev->bm.bm_lock); + return NOPFN_REFAULT; + } + + err = drm_bo_wait(bo, 0, 1, 0, 1); + if (err) { + ret = (err != -EAGAIN) ? NOPFN_SIGBUS : NOPFN_REFAULT; + bo->priv_flags &= ~_DRM_BO_FLAG_UNLOCKED; + goto out_unlock; + } + + bo->priv_flags &= ~_DRM_BO_FLAG_UNLOCKED; + + /* + * If buffer happens to be in a non-mappable location, + * move it to a mappable. + */ + + if (!(bo->mem.flags & DRM_BO_FLAG_MAPPABLE)) { + uint32_t new_flags = bo->mem.proposed_flags | + DRM_BO_FLAG_MAPPABLE | + DRM_BO_FLAG_FORCE_MAPPABLE; + err = drm_bo_move_buffer(bo, new_flags, 0, 0); + if (err) { + ret = (err != -EAGAIN) ? NOPFN_SIGBUS : NOPFN_REFAULT; + goto out_unlock; + } + } + + err = drm_bo_pci_offset(dev, &bo->mem, &bus_base, &bus_offset, + &bus_size); + + if (err) { + ret = NOPFN_SIGBUS; + goto out_unlock; + } + + page_offset = (address - vma->vm_start) >> PAGE_SHIFT; + + if (bus_size) { + struct drm_mem_type_manager *man = &dev->bm.man[bo->mem.mem_type]; + + pfn = ((bus_base + bus_offset) >> PAGE_SHIFT) + page_offset; + vma->vm_page_prot = drm_io_prot(man->drm_bus_maptype, vma); + } else { + ttm = bo->ttm; + + drm_ttm_fixup_caching(ttm); + page = drm_ttm_get_page(ttm, page_offset); + if (!page) { + ret = NOPFN_OOM; + goto out_unlock; + } + pfn = page_to_pfn(page); + vma->vm_page_prot = (bo->mem.flags & DRM_BO_FLAG_CACHED) ? + vm_get_page_prot(vma->vm_flags) : + drm_io_prot(_DRM_TTM, vma); + } + + err = vm_insert_pfn(vma, address, pfn); + if (err) { + ret = (err != -EAGAIN) ? NOPFN_OOM : NOPFN_REFAULT; + goto out_unlock; + } +out_unlock: + BUG_ON(bo->priv_flags & _DRM_BO_FLAG_UNLOCKED); + mutex_unlock(&bo->mutex); + drm_bo_read_unlock(&dev->bm.bm_lock); + return ret; +} +#endif +#endif diff --git a/linux-core/drm_compat.h b/linux-core/drm_compat.h index 6e5d252b..7ddc2c97 100644 --- a/linux-core/drm_compat.h +++ b/linux-core/drm_compat.h @@ -312,6 +312,9 @@ extern int drm_bo_map_bound(struct vm_area_struct *vma); /* fixme when functions are upstreamed - upstreamed for 2.6.23 */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)) #define DRM_IDR_COMPAT_FN +#define DRM_NO_FAULT +extern unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, + unsigned long address); #endif #ifdef DRM_IDR_COMPAT_FN int idr_for_each(struct idr *idp, diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 6618c0ae..0d5242d3 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -685,8 +685,8 @@ EXPORT_SYMBOL(drm_mmap); * \c Pagefault method for buffer objects. * * \param vma Virtual memory area. - * \param address File offset. - * \return Error or refault. The pfn is manually inserted. + * \param vmf vm fault data + * \return Error or VM_FAULT_NOPAGE:. The pfn is manually inserted. * * It's important that pfns are inserted while holding the bo->mutex lock. * otherwise we might race with unmap_mapping_range() which is always @@ -699,8 +699,8 @@ EXPORT_SYMBOL(drm_mmap); */ #ifdef DRM_FULL_MM_COMPAT -static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, - unsigned long address) +static int drm_bo_vm_fault(struct vm_area_struct *vma, + struct vm_fault *vmf) { struct drm_buffer_object *bo = (struct drm_buffer_object *) vma->vm_private_data; unsigned long page_offset; @@ -712,25 +712,22 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, unsigned long bus_base; unsigned long bus_offset; unsigned long bus_size; - unsigned long ret = NOPFN_REFAULT; - - if (address > vma->vm_end) - return NOPFN_SIGBUS; + unsigned long ret = VM_FAULT_NOPAGE; dev = bo->dev; err = drm_bo_read_lock(&dev->bm.bm_lock, 1); if (err) - return NOPFN_REFAULT; + return VM_FAULT_NOPAGE; err = mutex_lock_interruptible(&bo->mutex); if (err) { drm_bo_read_unlock(&dev->bm.bm_lock); - return NOPFN_REFAULT; + return VM_FAULT_NOPAGE; } err = drm_bo_wait(bo, 0, 1, 0, 1); if (err) { - ret = (err != -EAGAIN) ? NOPFN_SIGBUS : NOPFN_REFAULT; + ret = (err != -EAGAIN) ? VM_FAULT_SIGBUS : VM_FAULT_NOPAGE; bo->priv_flags &= ~_DRM_BO_FLAG_UNLOCKED; goto out_unlock; } @@ -748,7 +745,7 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, DRM_BO_FLAG_FORCE_MAPPABLE; err = drm_bo_move_buffer(bo, new_flags, 0, 0); if (err) { - ret = (err != -EAGAIN) ? NOPFN_SIGBUS : NOPFN_REFAULT; + ret = (err != -EAGAIN) ? VM_FAULT_SIGBUS : VM_FAULT_NOPAGE; goto out_unlock; } } @@ -757,11 +754,11 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, &bus_size); if (err) { - ret = NOPFN_SIGBUS; + ret = VM_FAULT_SIGBUS; goto out_unlock; } - page_offset = (address - vma->vm_start) >> PAGE_SHIFT; + page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> PAGE_SHIFT; if (bus_size) { struct drm_mem_type_manager *man = &dev->bm.man[bo->mem.mem_type]; @@ -774,7 +771,7 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, drm_ttm_fixup_caching(ttm); page = drm_ttm_get_page(ttm, page_offset); if (!page) { - ret = NOPFN_OOM; + ret = VM_FAULT_OOM; goto out_unlock; } pfn = page_to_pfn(page); @@ -783,9 +780,9 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, drm_io_prot(_DRM_TTM, vma); } - err = vm_insert_pfn(vma, address, pfn); + err = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); if (err) { - ret = (err != -EAGAIN) ? NOPFN_OOM : NOPFN_REFAULT; + ret = (err != -EAGAIN) ? VM_FAULT_OOM : VM_FAULT_NOPAGE; goto out_unlock; } out_unlock: @@ -849,8 +846,12 @@ static void drm_bo_vm_close(struct vm_area_struct *vma) static struct vm_operations_struct drm_bo_vm_ops = { #ifdef DRM_FULL_MM_COMPAT +#ifdef DRM_NO_FAULT .nopfn = drm_bo_vm_nopfn, #else + .fault = drm_bo_vm_fault, +#endif +#else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) .nopfn = drm_bo_vm_nopfn, #else diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index e0eb6335..28923201 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -80,7 +80,9 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) i915_save_state(dev); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) intel_opregion_free(dev); +#endif if (state.event == PM_EVENT_SUSPEND) { /* Shut down the device */ @@ -101,7 +103,9 @@ static int i915_resume(struct drm_device *dev) i915_restore_state(dev); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) intel_opregion_init(dev); +#endif return 0; } diff --git a/linux-core/i915_opregion.c b/linux-core/i915_opregion.c index 015376f8..1fa599ea 100644 --- a/linux-core/i915_opregion.c +++ b/linux-core/i915_opregion.c @@ -32,6 +32,7 @@ #include "i915_drm.h" #include "i915_drv.h" +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) #define PCI_ASLE 0xe4 #define PCI_ASLS 0xfc @@ -385,3 +386,4 @@ void intel_opregion_free(struct drm_device *dev) opregion->enabled = 0; } +#endif diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 13ba5b3f..5811fa3c 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1046,7 +1046,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) { struct drm_i915_private *dev_priv; unsigned long base, size; - int ret = 0, num_pipes = 2, mmio_bar = IS_I9XX(dev) ? 0 : 1; + int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1; /* i915 has 4 more counters */ dev->counters += 4; @@ -1077,8 +1077,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) intel_init_chipset_flush_compat(dev); #endif +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) intel_opregion_init(dev); #endif +#endif /* Init HWS */ if (!I915_NEED_GFX_HWS(dev)) { @@ -1087,65 +1089,22 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) return ret; } - I915_WRITE16(HWSTAM, 0xeffe); - I915_WRITE16(IMR, 0x0); - I915_WRITE16(IER, 0x0); - - DRM_SPININIT(&dev_priv->swaps_lock, "swap"); - INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); - dev_priv->swaps_pending = 0; - - DRM_SPININIT(&dev_priv->user_irq_lock, "userirq"); - dev_priv->user_irq_refcount = 0; - dev_priv->irq_mask_reg = ~0; - - ret = drm_vblank_init(dev, num_pipes); - if (ret) - return ret; - - dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; - dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ - - i915_enable_interrupt(dev); - DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); - - /* - * Initialize the hardware status page IRQ location. - */ - - I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); - return ret; } int i915_driver_unload(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - u32 temp; - - if (dev_priv) { - dev_priv->vblank_pipe = 0; - - dev_priv->irq_enabled = 0; - I915_WRITE(HWSTAM, 0xffffffff); - I915_WRITE(IMR, 0xffffffff); - I915_WRITE(IER, 0x0); - - temp = I915_READ(PIPEASTAT); - I915_WRITE(PIPEASTAT, temp); - temp = I915_READ(PIPEBSTAT); - I915_WRITE(PIPEBSTAT, temp); - temp = I915_READ(IIR); - I915_WRITE(IIR, temp); - } i915_free_hardware_status(dev); drm_rmmap(dev, dev_priv->mmio_map); #ifdef __linux__ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) intel_opregion_free(dev); #endif +#endif drm_free(dev->dev_private, sizeof(drm_i915_private_t), DRM_MEM_DRIVER); diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index fe52845e..f84dcc25 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -488,7 +488,6 @@ extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); extern void i915_driver_irq_preinstall(struct drm_device * dev); extern int i915_driver_irq_postinstall(struct drm_device * dev); extern void i915_driver_irq_uninstall(struct drm_device * dev); -extern void i915_enable_interrupt(struct drm_device *dev); extern int i915_vblank_pipe_set(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int i915_vblank_pipe_get(struct drm_device *dev, void *data, diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index fe617557..418e0ae9 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -480,16 +480,20 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) } #ifdef __linux__ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) if (pipeb_stats & I915_LEGACY_BLC_EVENT_ENABLE) opregion_asle_intr(dev); #endif +#endif I915_WRITE(PIPEBSTAT, pipeb_stats); } #ifdef __linux__ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) if (iir & I915_ASLE_INTERRUPT) opregion_asle_intr(dev); #endif +#endif if (dev_priv->sarea_priv) dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); @@ -720,7 +724,7 @@ void i915_disable_vblank(struct drm_device *dev, int plane) } } -void i915_enable_interrupt (struct drm_device *dev) +static void i915_enable_interrupt (struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -730,8 +734,10 @@ void i915_enable_interrupt (struct drm_device *dev) (void) I915_READ (IER); #ifdef __linux__ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) opregion_enable_asle(dev); #endif +#endif dev_priv->irq_enabled = 1; } @@ -930,15 +936,63 @@ int i915_vblank_swap(struct drm_device *dev, void *data, */ void i915_driver_irq_preinstall(struct drm_device * dev) { - return; + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + + I915_WRITE16(HWSTAM, 0xeffe); + I915_WRITE16(IMR, 0x0); + I915_WRITE16(IER, 0x0); } int i915_driver_irq_postinstall(struct drm_device * dev) { + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + int ret, num_pipes = 2; + + DRM_SPININIT(&dev_priv->swaps_lock, "swap"); + INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); + dev_priv->swaps_pending = 0; + + DRM_SPININIT(&dev_priv->user_irq_lock, "userirq"); + dev_priv->user_irq_refcount = 0; + dev_priv->irq_mask_reg = ~0; + + ret = drm_vblank_init(dev, num_pipes); + if (ret) + return ret; + + dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; + dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ + + i915_enable_interrupt(dev); + DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); + + /* + * Initialize the hardware status page IRQ location. + */ + + I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); return 0; } void i915_driver_irq_uninstall(struct drm_device * dev) { - return; + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + u32 temp; + + if (!dev_priv) + return; + + dev_priv->vblank_pipe = 0; + + dev_priv->irq_enabled = 0; + I915_WRITE(HWSTAM, 0xffffffff); + I915_WRITE(IMR, 0xffffffff); + I915_WRITE(IER, 0x0); + + temp = I915_READ(PIPEASTAT); + I915_WRITE(PIPEASTAT, temp); + temp = I915_READ(PIPEBSTAT); + I915_WRITE(PIPEBSTAT, temp); + temp = I915_READ(IIR); + I915_WRITE(IIR, temp); } diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 085336af..5ec2bc3e 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -131,7 +131,7 @@ int nouveau_fifo_init(struct drm_device *dev) /* No cmdbuf object */ NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE, 0x00000000); NV_WRITE(NV03_PFIFO_CACHE0_PUSH0, 0x00000000); - NV_WRITE(NV03_PFIFO_CACHE0_PULL0, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE0_PULL0, 0x00000000); NV_WRITE(NV04_PFIFO_SIZE, 0x0000FFFF); NV_WRITE(NV04_PFIFO_CACHE1_HASH, 0x0000FFFF); NV_WRITE(NV04_PFIFO_CACHE0_PULL1, 0x00000001); diff --git a/shared-core/nv04_fifo.c b/shared-core/nv04_fifo.c index 230c8e72..88186fe3 100644 --- a/shared-core/nv04_fifo.c +++ b/shared-core/nv04_fifo.c @@ -122,8 +122,8 @@ nv04_fifo_save_context(struct nouveau_channel *chan) struct drm_nouveau_private *dev_priv = dev->dev_private; uint32_t tmp; - RAMFC_WR(DMA_PUT, NV04_PFIFO_CACHE1_DMA_PUT); - RAMFC_WR(DMA_GET, NV04_PFIFO_CACHE1_DMA_GET); + RAMFC_WR(DMA_PUT, NV_READ(NV04_PFIFO_CACHE1_DMA_PUT)); + RAMFC_WR(DMA_GET, NV_READ(NV04_PFIFO_CACHE1_DMA_GET)); tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16; tmp |= NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE); diff --git a/shared-core/nv40_graph.c b/shared-core/nv40_graph.c index 2540fc5f..de178f57 100644 --- a/shared-core/nv40_graph.c +++ b/shared-core/nv40_graph.c @@ -1544,6 +1544,8 @@ nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) tmp |= NV40_PGRAPH_CTXCTL_0304_XFER_CTX; NV_WRITE(NV40_PGRAPH_CTXCTL_0304, tmp); + nouveau_wait_for_idle(dev); + for (i = 0; i < tv; i++) { if (NV_READ(NV40_PGRAPH_CTXCTL_030C) == 0) break; @@ -1565,9 +1567,7 @@ nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) return 0; } -/* Save current context (from PGRAPH) into the channel's context - *XXX: fails sometimes, not sure why.. - */ +/* Save current context (from PGRAPH) into the channel's context */ int nv40_graph_save_context(struct nouveau_channel *chan) { @@ -1581,9 +1581,7 @@ nv40_graph_save_context(struct nouveau_channel *chan) return nv40_graph_transfer_context(dev, inst, 1); } -/* Restore the context for a specific channel into PGRAPH - * XXX: fails sometimes.. not sure why - */ +/* Restore the context for a specific channel into PGRAPH */ int nv40_graph_load_context(struct nouveau_channel *chan) { diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c index ed787461..7546e839 100644 --- a/shared-core/r300_cmdbuf.c +++ b/shared-core/r300_cmdbuf.c @@ -77,6 +77,9 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, return -EFAULT; } + box.x2--; /* Hardware expects inclusive bottom-right corner */ + box.y2--; + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { box.x1 = (box.x1) & R300_CLIPRECT_MASK; @@ -95,8 +98,8 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, R300_CLIPRECT_MASK; box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK; - } + OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) | (box.y1 << R300_CLIPRECT_Y_SHIFT)); OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) | |