Commit 531e7713 authored by Ben Skeggs's avatar Ben Skeggs

drm/nv50: improve vram page table construction

This commit changes nouveau to construct PTEs which look very much like
the ones the binary driver creates.

I presume that filling multiple PTEs identically with length flags and
the physical address of the start of a block of VRAM is a hint to the
memory controller that it need not perform additional page table lookups
for that range of addresses.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 4c27bd33
...@@ -285,23 +285,45 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size, ...@@ -285,23 +285,45 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
uint32_t flags, uint64_t phys) uint32_t flags, uint64_t phys)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
unsigned pages; struct nouveau_gpuobj *pgt;
unsigned block;
int i;
virt -= dev_priv->vm_vram_base; virt = ((virt - dev_priv->vm_vram_base) >> 16) << 1;
pages = size >> 16; size = (size >> 16) << 1;
phys |= ((uint64_t)flags << 32) | 1;
dev_priv->engine.instmem.prepare_access(dev, true); dev_priv->engine.instmem.prepare_access(dev, true);
while (pages--) { while (size) {
struct nouveau_gpuobj *pt = dev_priv->vm_vram_pt[virt >> 29]; unsigned offset_h = upper_32_bits(phys);
unsigned pte = ((virt & 0x1fffffffULL) >> 16) << 1;
unsigned offset_h = upper_32_bits(phys) & 0xff;
unsigned offset_l = lower_32_bits(phys); unsigned offset_l = lower_32_bits(phys);
unsigned pte, end;
for (i = 7; i >= 0; i--) {
block = 1 << (i + 1);
if (size >= block && !(virt & (block - 1)))
break;
}
offset_l |= (i << 7);
nv_wo32(dev, pt, pte++, offset_l | 1); phys += block << 15;
nv_wo32(dev, pt, pte++, offset_h | flags); size -= block;
phys += (1 << 16); while (block) {
virt += (1 << 16); pgt = dev_priv->vm_vram_pt[virt >> 14];
pte = virt & 0x3ffe;
end = pte + block;
if (end > 16384)
end = 16384;
block -= (end - pte);
virt += (end - pte);
while (pte < end) {
nv_wo32(dev, pgt, pte++, offset_l);
nv_wo32(dev, pgt, pte++, offset_h);
}
}
} }
dev_priv->engine.instmem.finish_access(dev); dev_priv->engine.instmem.finish_access(dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment