From: Ben Skeggs Date: Thu, 11 Feb 2010 00:25:53 +0000 (+1000) Subject: drm/nv50: more efficient clearing of gpu page table entries X-Git-Tag: v2.6.33~7^2~1^2~3 X-Git-Url: http://git.cascardo.eti.br/?a=commitdiff_plain;h=4c27bd339d226175ac0e4dc3ab8289ba696db8be;p=cascardo%2Flinux.git drm/nv50: more efficient clearing of gpu page table entries Signed-off-by: Ben Skeggs --- diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 04885d2fb15f..6832c4c969a3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -291,31 +291,17 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size, pages = size >> 16; dev_priv->engine.instmem.prepare_access(dev, true); - if (flags & 0x80000000) { - while (pages--) { - struct nouveau_gpuobj *pt = - dev_priv->vm_vram_pt[virt >> 29]; - unsigned pte = ((virt & 0x1fffffffULL) >> 16) << 1; + while (pages--) { + struct nouveau_gpuobj *pt = dev_priv->vm_vram_pt[virt >> 29]; + unsigned pte = ((virt & 0x1fffffffULL) >> 16) << 1; + unsigned offset_h = upper_32_bits(phys) & 0xff; + unsigned offset_l = lower_32_bits(phys); - nv_wo32(dev, pt, pte++, 0x00000000); - nv_wo32(dev, pt, pte++, 0x00000000); + nv_wo32(dev, pt, pte++, offset_l | 1); + nv_wo32(dev, pt, pte++, offset_h | flags); - virt += (1 << 16); - } - } else { - while (pages--) { - struct nouveau_gpuobj *pt = - dev_priv->vm_vram_pt[virt >> 29]; - unsigned pte = ((virt & 0x1fffffffULL) >> 16) << 1; - unsigned offset_h = upper_32_bits(phys) & 0xff; - unsigned offset_l = lower_32_bits(phys); - - nv_wo32(dev, pt, pte++, offset_l | 1); - nv_wo32(dev, pt, pte++, offset_h | flags); - - phys += (1 << 16); - virt += (1 << 16); - } + phys += (1 << 16); + virt += (1 << 16); } dev_priv->engine.instmem.finish_access(dev); @@ -339,7 +325,41 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size, void nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) { - nv50_mem_vm_bind_linear(dev, virt, size, 0x80000000, 0); + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *pgt; + unsigned pages, pte, end; + + virt -= dev_priv->vm_vram_base; + pages = (size >> 16) << 1; + + dev_priv->engine.instmem.prepare_access(dev, true); + while (pages) { + pgt = dev_priv->vm_vram_pt[virt >> 29]; + pte = (virt & 0x1ffe0000ULL) >> 15; + + end = pte + pages; + if (end > 16384) + end = 16384; + pages -= (end - pte); + virt += (end - pte) << 15; + + while (pte < end) + nv_wo32(dev, pgt, pte++, 0); + } + dev_priv->engine.instmem.finish_access(dev); + + nv_wr32(dev, 0x100c80, 0x00050001); + if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { + NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); + NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); + return; + } + + nv_wr32(dev, 0x100c80, 0x00000001); + if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { + NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); + NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); + } } /*