Commit ad76b3f7 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau: teach nouveau_bo_pin() how to force a contig vram allocation

We have the ability to move buffers around in the kernel if necessary,
and should probably use it rather than failing if userspace passes us
a non-contig buffer for a plane.

The NOUVEAU_GEM_TILE_NONCONTIG flag from userspace will become a mere
initial placement hint once all the relevant paths have been updated.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent ef1df1bc
...@@ -614,7 +614,7 @@ nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) ...@@ -614,7 +614,7 @@ nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
int ret; int ret;
ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM, false);
if (ret == 0) { if (ret == 0) {
if (disp->image[nv_crtc->index]) if (disp->image[nv_crtc->index])
nouveau_bo_unpin(disp->image[nv_crtc->index]); nouveau_bo_unpin(disp->image[nv_crtc->index]);
...@@ -1130,7 +1130,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) ...@@ -1130,7 +1130,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num)
ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
0, 0x0000, NULL, NULL, &nv_crtc->cursor.nvbo); 0, 0x0000, NULL, NULL, &nv_crtc->cursor.nvbo);
if (!ret) { if (!ret) {
ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM, false);
if (!ret) { if (!ret) {
ret = nouveau_bo_map(nv_crtc->cursor.nvbo); ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
if (ret) if (ret)
......
...@@ -126,7 +126,7 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -126,7 +126,7 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
return -ERANGE; return -ERANGE;
} }
ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM, false);
if (ret) if (ret)
return ret; return ret;
...@@ -373,7 +373,7 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -373,7 +373,7 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
if (crtc_w < src_w || crtc_h < src_h) if (crtc_w < src_w || crtc_h < src_h)
return -ERANGE; return -ERANGE;
ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM, false);
if (ret) if (ret)
return ret; return ret;
......
...@@ -308,7 +308,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) ...@@ -308,7 +308,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
ret = nouveau_gem_new(dev, PAGE_SIZE, 0, NOUVEAU_GEM_DOMAIN_GART, ret = nouveau_gem_new(dev, PAGE_SIZE, 0, NOUVEAU_GEM_DOMAIN_GART,
0, 0, &chan->ntfy); 0, 0, &chan->ntfy);
if (ret == 0) if (ret == 0)
ret = nouveau_bo_pin(chan->ntfy, TTM_PL_FLAG_TT); ret = nouveau_bo_pin(chan->ntfy, TTM_PL_FLAG_TT, false);
if (ret) if (ret)
goto done; goto done;
......
...@@ -310,26 +310,49 @@ nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t type, uint32_t busy) ...@@ -310,26 +310,49 @@ nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t type, uint32_t busy)
} }
int int
nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype) nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype, bool contig)
{ {
struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
struct ttm_buffer_object *bo = &nvbo->bo; struct ttm_buffer_object *bo = &nvbo->bo;
bool force = false, evict = false;
int ret; int ret;
ret = ttm_bo_reserve(bo, false, false, false, NULL); ret = ttm_bo_reserve(bo, false, false, false, NULL);
if (ret) if (ret)
return ret; return ret;
if (nvbo->pin_refcnt && !(memtype & (1 << bo->mem.mem_type))) { if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA &&
NV_ERROR(drm, "bo %p pinned elsewhere: 0x%08x vs 0x%08x\n", bo, memtype == TTM_PL_FLAG_VRAM && contig) {
if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) {
if (bo->mem.mem_type == TTM_PL_VRAM) {
struct nouveau_mem *mem = bo->mem.mm_node;
if (!list_is_singular(&mem->regions))
evict = true;
}
nvbo->tile_flags &= ~NOUVEAU_GEM_TILE_NONCONTIG;
force = true;
}
}
if (nvbo->pin_refcnt) {
if (!(memtype & (1 << bo->mem.mem_type)) || evict) {
NV_ERROR(drm, "bo %p pinned elsewhere: "
"0x%08x vs 0x%08x\n", bo,
1 << bo->mem.mem_type, memtype); 1 << bo->mem.mem_type, memtype);
ret = -EINVAL; ret = -EBUSY;
}
nvbo->pin_refcnt++;
goto out; goto out;
} }
if (nvbo->pin_refcnt++) if (evict) {
nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_TT, 0);
ret = nouveau_bo_validate(nvbo, false, false);
if (ret)
goto out; goto out;
}
nvbo->pin_refcnt++;
nouveau_bo_placement_set(nvbo, memtype, 0); nouveau_bo_placement_set(nvbo, memtype, 0);
/* drop pin_refcnt temporarily, so we don't trip the assertion /* drop pin_refcnt temporarily, so we don't trip the assertion
...@@ -354,6 +377,8 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype) ...@@ -354,6 +377,8 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype)
} }
out: out:
if (force && ret)
nvbo->tile_flags |= NOUVEAU_GEM_TILE_NONCONTIG;
ttm_bo_unreserve(bo); ttm_bo_unreserve(bo);
return ret; return ret;
} }
......
...@@ -73,7 +73,7 @@ int nouveau_bo_new(struct drm_device *, int size, int align, u32 flags, ...@@ -73,7 +73,7 @@ int nouveau_bo_new(struct drm_device *, int size, int align, u32 flags,
u32 tile_mode, u32 tile_flags, struct sg_table *sg, u32 tile_mode, u32 tile_flags, struct sg_table *sg,
struct reservation_object *robj, struct reservation_object *robj,
struct nouveau_bo **); struct nouveau_bo **);
int nouveau_bo_pin(struct nouveau_bo *, u32 flags); int nouveau_bo_pin(struct nouveau_bo *, u32 flags, bool contig);
int nouveau_bo_unpin(struct nouveau_bo *); int nouveau_bo_unpin(struct nouveau_bo *);
int nouveau_bo_map(struct nouveau_bo *); int nouveau_bo_map(struct nouveau_bo *);
void nouveau_bo_unmap(struct nouveau_bo *); void nouveau_bo_unmap(struct nouveau_bo *);
......
...@@ -109,7 +109,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, ...@@ -109,7 +109,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
ret = nouveau_bo_new(drm->dev, size, 0, target, 0, 0, NULL, NULL, ret = nouveau_bo_new(drm->dev, size, 0, target, 0, 0, NULL, NULL,
&chan->push.buffer); &chan->push.buffer);
if (ret == 0) { if (ret == 0) {
ret = nouveau_bo_pin(chan->push.buffer, target); ret = nouveau_bo_pin(chan->push.buffer, target, false);
if (ret == 0) if (ret == 0)
ret = nouveau_bo_map(chan->push.buffer); ret = nouveau_bo_map(chan->push.buffer);
} }
......
...@@ -592,7 +592,7 @@ nouveau_display_resume(struct drm_device *dev, bool runtime) ...@@ -592,7 +592,7 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
if (!nouveau_fb || !nouveau_fb->nvbo) if (!nouveau_fb || !nouveau_fb->nvbo)
continue; continue;
ret = nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM, false);
if (ret) if (ret)
NV_ERROR(drm, "Could not pin framebuffer\n"); NV_ERROR(drm, "Could not pin framebuffer\n");
} }
...@@ -600,7 +600,7 @@ nouveau_display_resume(struct drm_device *dev, bool runtime) ...@@ -600,7 +600,7 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM, false);
if (!ret) if (!ret)
ret = nouveau_bo_map(nv_crtc->cursor.nvbo); ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
if (ret) if (ret)
...@@ -713,7 +713,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -713,7 +713,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
return -ENOMEM; return -ENOMEM;
if (new_bo != old_bo) { if (new_bo != old_bo) {
ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM, false);
if (ret) if (ret)
goto fail_free; goto fail_free;
} }
......
...@@ -341,7 +341,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper, ...@@ -341,7 +341,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
goto out; goto out;
} }
ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM, false);
if (ret) { if (ret) {
NV_ERROR(drm, "failed to pin fb: %d\n", ret); NV_ERROR(drm, "failed to pin fb: %d\n", ret);
goto out_unref; goto out_unref;
......
...@@ -93,7 +93,7 @@ int nouveau_gem_prime_pin(struct drm_gem_object *obj) ...@@ -93,7 +93,7 @@ int nouveau_gem_prime_pin(struct drm_gem_object *obj)
int ret; int ret;
/* pin buffer into GTT */ /* pin buffer into GTT */
ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_TT); ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_TT, false);
if (ret) if (ret)
return -EINVAL; return -EINVAL;
......
...@@ -131,7 +131,7 @@ nv17_fence_create(struct nouveau_drm *drm) ...@@ -131,7 +131,7 @@ nv17_fence_create(struct nouveau_drm *drm)
ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
0, 0x0000, NULL, NULL, &priv->bo); 0, 0x0000, NULL, NULL, &priv->bo);
if (!ret) { if (!ret) {
ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM, false);
if (!ret) { if (!ret) {
ret = nouveau_bo_map(priv->bo); ret = nouveau_bo_map(priv->bo);
if (ret) if (ret)
......
...@@ -1073,7 +1073,7 @@ nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) ...@@ -1073,7 +1073,7 @@ nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
struct nv50_head *head = nv50_head(crtc); struct nv50_head *head = nv50_head(crtc);
int ret; int ret;
ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM, false);
if (ret == 0) { if (ret == 0) {
if (head->image) if (head->image)
nouveau_bo_unpin(head->image); nouveau_bo_unpin(head->image);
...@@ -1402,7 +1402,7 @@ nv50_crtc_create(struct drm_device *dev, int index) ...@@ -1402,7 +1402,7 @@ nv50_crtc_create(struct drm_device *dev, int index)
ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM, ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM,
0, 0x0000, NULL, NULL, &head->base.lut.nvbo); 0, 0x0000, NULL, NULL, &head->base.lut.nvbo);
if (!ret) { if (!ret) {
ret = nouveau_bo_pin(head->base.lut.nvbo, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(head->base.lut.nvbo, TTM_PL_FLAG_VRAM, false);
if (!ret) { if (!ret) {
ret = nouveau_bo_map(head->base.lut.nvbo); ret = nouveau_bo_map(head->base.lut.nvbo);
if (ret) if (ret)
...@@ -1425,7 +1425,7 @@ nv50_crtc_create(struct drm_device *dev, int index) ...@@ -1425,7 +1425,7 @@ nv50_crtc_create(struct drm_device *dev, int index)
ret = nouveau_bo_new(dev, 64 * 64 * 4, 0x100, TTM_PL_FLAG_VRAM, ret = nouveau_bo_new(dev, 64 * 64 * 4, 0x100, TTM_PL_FLAG_VRAM,
0, 0x0000, NULL, NULL, &head->base.cursor.nvbo); 0, 0x0000, NULL, NULL, &head->base.cursor.nvbo);
if (!ret) { if (!ret) {
ret = nouveau_bo_pin(head->base.cursor.nvbo, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(head->base.cursor.nvbo, TTM_PL_FLAG_VRAM, false);
if (!ret) { if (!ret) {
ret = nouveau_bo_map(head->base.cursor.nvbo); ret = nouveau_bo_map(head->base.cursor.nvbo);
if (ret) if (ret)
...@@ -2487,7 +2487,7 @@ nv50_display_create(struct drm_device *dev) ...@@ -2487,7 +2487,7 @@ nv50_display_create(struct drm_device *dev)
ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
0, 0x0000, NULL, NULL, &disp->sync); 0, 0x0000, NULL, NULL, &disp->sync);
if (!ret) { if (!ret) {
ret = nouveau_bo_pin(disp->sync, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(disp->sync, TTM_PL_FLAG_VRAM, false);
if (!ret) { if (!ret) {
ret = nouveau_bo_map(disp->sync); ret = nouveau_bo_map(disp->sync);
if (ret) if (ret)
......
...@@ -102,7 +102,7 @@ nv50_fence_create(struct nouveau_drm *drm) ...@@ -102,7 +102,7 @@ nv50_fence_create(struct nouveau_drm *drm)
ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
0, 0x0000, NULL, NULL, &priv->bo); 0, 0x0000, NULL, NULL, &priv->bo);
if (!ret) { if (!ret) {
ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM, false);
if (!ret) { if (!ret) {
ret = nouveau_bo_map(priv->bo); ret = nouveau_bo_map(priv->bo);
if (ret) if (ret)
......
...@@ -234,7 +234,7 @@ nv84_fence_create(struct nouveau_drm *drm) ...@@ -234,7 +234,7 @@ nv84_fence_create(struct nouveau_drm *drm)
ret = nouveau_bo_new(drm->dev, 16 * priv->base.contexts, 0, ret = nouveau_bo_new(drm->dev, 16 * priv->base.contexts, 0,
TTM_PL_FLAG_VRAM, 0, 0, NULL, NULL, &priv->bo); TTM_PL_FLAG_VRAM, 0, 0, NULL, NULL, &priv->bo);
if (ret == 0) { if (ret == 0) {
ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM, false);
if (ret == 0) { if (ret == 0) {
ret = nouveau_bo_map(priv->bo); ret = nouveau_bo_map(priv->bo);
if (ret) if (ret)
...@@ -249,7 +249,7 @@ nv84_fence_create(struct nouveau_drm *drm) ...@@ -249,7 +249,7 @@ nv84_fence_create(struct nouveau_drm *drm)
TTM_PL_FLAG_TT | TTM_PL_FLAG_UNCACHED, 0, TTM_PL_FLAG_TT | TTM_PL_FLAG_UNCACHED, 0,
0, NULL, NULL, &priv->bo_gart); 0, NULL, NULL, &priv->bo_gart);
if (ret == 0) { if (ret == 0) {
ret = nouveau_bo_pin(priv->bo_gart, TTM_PL_FLAG_TT); ret = nouveau_bo_pin(priv->bo_gart, TTM_PL_FLAG_TT, false);
if (ret == 0) { if (ret == 0) {
ret = nouveau_bo_map(priv->bo_gart); ret = nouveau_bo_map(priv->bo_gart);
if (ret) if (ret)
......
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