diff options
Diffstat (limited to 'shared-core/nouveau_mem.c')
-rw-r--r-- | shared-core/nouveau_mem.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c index d79c1a52..1078a9c5 100644 --- a/shared-core/nouveau_mem.c +++ b/shared-core/nouveau_mem.c @@ -34,6 +34,7 @@ #include "drm.h" #include "drm_sarea.h" #include "nouveau_drv.h" +#include "nv50_kms_wrapper.h" static struct mem_block * split_block(struct mem_block *p, uint64_t start, uint64_t size, @@ -120,6 +121,17 @@ static struct mem_block *find_block(struct mem_block *heap, uint64_t start) return NULL; } +struct mem_block *find_block_by_handle(struct mem_block *heap, drm_handle_t handle) +{ + struct mem_block *p; + + list_for_each(p, heap) + if (p->map_handle == handle) + return p; + + return NULL; +} + void nouveau_mem_free_block(struct mem_block *p) { p->file_priv = NULL; @@ -734,6 +746,30 @@ void nouveau_mem_free(struct drm_device* dev, struct mem_block* block) DRM_DEBUG("freeing 0x%llx type=0x%08x\n", block->start, block->flags); + /* Check if the deallocations cause problems for our modesetting system. */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + if (dev_priv->card_type >= NV_50) { + struct nv50_crtc *crtc = NULL; + struct nv50_display *display = nv50_get_display(dev); + + list_for_each_entry(crtc, &display->crtcs, item) { + if (crtc->fb->block == block) { + crtc->fb->block = NULL; + + if (!crtc->blanked) + crtc->blank(crtc, true); + } + + if (crtc->cursor->block == block) { + crtc->cursor->block = NULL; + + if (crtc->cursor->visible) + crtc->cursor->hide(crtc); + } + } + } + } + if (block->flags&NOUVEAU_MEM_MAPPED) drm_rmmap(dev, block->map); |