diff options
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_mem.c | 44 |
1 files changed, 33 insertions, 11 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 6832c4c969a3..134fedbb7669 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c | |||
| @@ -285,23 +285,45 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size, | |||
| 285 | uint32_t flags, uint64_t phys) | 285 | uint32_t flags, uint64_t phys) |
| 286 | { | 286 | { |
| 287 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 287 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 288 | unsigned pages; | 288 | struct nouveau_gpuobj *pgt; |
| 289 | unsigned block; | ||
| 290 | int i; | ||
| 289 | 291 | ||
| 290 | virt -= dev_priv->vm_vram_base; | 292 | virt = ((virt - dev_priv->vm_vram_base) >> 16) << 1; |
| 291 | pages = size >> 16; | 293 | size = (size >> 16) << 1; |
| 294 | phys |= ((uint64_t)flags << 32) | 1; | ||
| 292 | 295 | ||
| 293 | dev_priv->engine.instmem.prepare_access(dev, true); | 296 | dev_priv->engine.instmem.prepare_access(dev, true); |
| 294 | while (pages--) { | 297 | while (size) { |
| 295 | struct nouveau_gpuobj *pt = dev_priv->vm_vram_pt[virt >> 29]; | 298 | unsigned offset_h = upper_32_bits(phys); |
| 296 | unsigned pte = ((virt & 0x1fffffffULL) >> 16) << 1; | ||
| 297 | unsigned offset_h = upper_32_bits(phys) & 0xff; | ||
| 298 | unsigned offset_l = lower_32_bits(phys); | 299 | unsigned offset_l = lower_32_bits(phys); |
| 300 | unsigned pte, end; | ||
| 301 | |||
| 302 | for (i = 7; i >= 0; i--) { | ||
| 303 | block = 1 << (i + 1); | ||
| 304 | if (size >= block && !(virt & (block - 1))) | ||
| 305 | break; | ||
| 306 | } | ||
| 307 | offset_l |= (i << 7); | ||
| 308 | |||
| 309 | phys += block << 15; | ||
| 310 | size -= block; | ||
| 299 | 311 | ||
| 300 | nv_wo32(dev, pt, pte++, offset_l | 1); | 312 | while (block) { |
| 301 | nv_wo32(dev, pt, pte++, offset_h | flags); | 313 | pgt = dev_priv->vm_vram_pt[virt >> 14]; |
| 314 | pte = virt & 0x3ffe; | ||
| 302 | 315 | ||
| 303 | phys += (1 << 16); | 316 | end = pte + block; |
| 304 | virt += (1 << 16); | 317 | if (end > 16384) |
| 318 | end = 16384; | ||
| 319 | block -= (end - pte); | ||
| 320 | virt += (end - pte); | ||
| 321 | |||
| 322 | while (pte < end) { | ||
| 323 | nv_wo32(dev, pgt, pte++, offset_l); | ||
| 324 | nv_wo32(dev, pgt, pte++, offset_h); | ||
| 325 | } | ||
| 326 | } | ||
| 305 | } | 327 | } |
| 306 | dev_priv->engine.instmem.finish_access(dev); | 328 | dev_priv->engine.instmem.finish_access(dev); |
| 307 | 329 | ||
