static int ttm_bo_man_takedown(struct ttm_mem_type_manager *man) { struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; struct drm_mm *mm = &rman->mm; spin_lock(&rman->lock); if (drm_mm_clean(mm)) { drm_mm_takedown(mm); spin_unlock(&rman->lock); kfree(rman); man->priv = NULL; return 0; } spin_unlock(&rman->lock); return -EBUSY; }
/** * amdgpu_vram_mgr_fini - free and destroy VRAM manager * * @man: TTM memory type manager * * Destroy and free the VRAM manager, returns -EBUSY if ranges are still * allocated inside it. */ static int amdgpu_vram_mgr_fini(struct ttm_mem_type_manager *man) { struct amdgpu_vram_mgr *mgr = man->priv; spin_lock(&mgr->lock); if (!drm_mm_clean(&mgr->mm)) { spin_unlock(&mgr->lock); return -EBUSY; } drm_mm_takedown(&mgr->mm); spin_unlock(&mgr->lock); kfree(mgr); man->priv = NULL; return 0; }
static int ttm_bo_man_takedown(struct ttm_mem_type_manager *man) { struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; struct drm_mm *mm = &rman->mm; lockmgr(&rman->lock, LK_EXCLUSIVE); if (drm_mm_clean(mm)) { drm_mm_takedown(mm); lockmgr(&rman->lock, LK_RELEASE); kfree(rman); man->priv = NULL; return 0; } lockmgr(&rman->lock, LK_RELEASE); return -EBUSY; }
static int ttm_bo_man_takedown(struct ttm_mem_type_manager *man) { struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; struct drm_mm *mm = &rman->mm; mtx_lock(&rman->lock); if (drm_mm_clean(mm)) { drm_mm_takedown(mm); mtx_unlock(&rman->lock); mtx_destroy(&rman->lock); free(rman, M_TTM_RMAN); man->priv = NULL; return 0; } mtx_unlock(&rman->lock); return -EBUSY; }
int ttm_bo_device_release(struct ttm_bo_device *bdev) { int ret = 0; unsigned i = TTM_NUM_MEM_TYPES; struct ttm_mem_type_manager *man; struct ttm_bo_global *glob = bdev->glob; while (i--) { man = &bdev->man[i]; if (man->has_type) { man->use_type = false; if ((i != TTM_PL_SYSTEM) && ttm_bo_clean_mm(bdev, i)) { ret = -EBUSY; printk(KERN_ERR TTM_PFX "DRM memory manager type %d " "is not clean.\n", i); } man->has_type = false; } } mutex_lock(&glob->device_list_mutex); list_del(&bdev->device_list); mutex_unlock(&glob->device_list_mutex); if (!cancel_delayed_work(&bdev->wq)) flush_scheduled_work(); while (ttm_bo_delayed_delete(bdev, true)) ; spin_lock(&glob->lru_lock); if (list_empty(&bdev->ddestroy)) TTM_DEBUG("Delayed destroy list was clean\n"); if (list_empty(&bdev->man[0].lru)) TTM_DEBUG("Swap list was clean\n"); spin_unlock(&glob->lru_lock); BUG_ON(!drm_mm_clean(&bdev->addr_space_mm)); write_lock(&bdev->vm_lock); drm_mm_takedown(&bdev->addr_space_mm); write_unlock(&bdev->vm_lock); return ret; }
int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) { struct ttm_bo_global *glob = bdev->glob; struct ttm_mem_type_manager *man; int ret = -EINVAL; if (mem_type >= TTM_NUM_MEM_TYPES) { printk(KERN_ERR TTM_PFX "Illegal memory type %d\n", mem_type); return ret; } man = &bdev->man[mem_type]; if (!man->has_type) { printk(KERN_ERR TTM_PFX "Trying to take down uninitialized " "memory manager type %u\n", mem_type); return ret; } man->use_type = false; man->has_type = false; ret = 0; if (mem_type > 0) { ttm_bo_force_list_clean(bdev, mem_type, false); spin_lock(&glob->lru_lock); if (drm_mm_clean(&man->manager)) drm_mm_takedown(&man->manager); else ret = -EBUSY; spin_unlock(&glob->lru_lock); } return ret; }