static int amdgpu_bo_list_create(struct amdgpu_device *adev, struct drm_file *filp, struct drm_amdgpu_bo_list_entry *info, unsigned num_entries, int *id) { int r; struct amdgpu_fpriv *fpriv = filp->driver_priv; struct amdgpu_bo_list *list; list = kzalloc(sizeof(struct amdgpu_bo_list), GFP_KERNEL); if (!list) return -ENOMEM; /* initialize bo list*/ mutex_init(&list->lock); kref_init(&list->refcount); r = amdgpu_bo_list_set(adev, filp, list, info, num_entries); if (r) { kfree(list); return r; } /* idr alloc should be called only after initialization of bo list. */ mutex_lock(&fpriv->bo_list_lock); r = idr_alloc(&fpriv->bo_list_handles, list, 1, 0, GFP_KERNEL); mutex_unlock(&fpriv->bo_list_lock); if (r < 0) { amdgpu_bo_list_free(list); return r; } *id = r; return 0; }
static void amdgpu_bo_list_destroy(struct amdgpu_fpriv *fpriv, int id) { struct amdgpu_bo_list *list; mutex_lock(&fpriv->bo_list_lock); list = idr_find(&fpriv->bo_list_handles, id); if (list) { mutex_lock(&list->lock); idr_remove(&fpriv->bo_list_handles, id); mutex_unlock(&list->lock); amdgpu_bo_list_free(list); } mutex_unlock(&fpriv->bo_list_lock); }
static void amdgpu_bo_list_destroy(struct amdgpu_fpriv *fpriv, int id) { struct amdgpu_bo_list *list; mutex_lock(&fpriv->bo_list_lock); list = idr_remove(&fpriv->bo_list_handles, id); if (list) { /* Another user may have a reference to this list still */ mutex_lock(&list->lock); mutex_unlock(&list->lock); amdgpu_bo_list_free(list); } mutex_unlock(&fpriv->bo_list_lock); }
/** * amdgpu_driver_postclose_kms - drm callback for post close * * @dev: drm dev pointer * @file_priv: drm file * * On device post close, tear down vm on cayman+ (all asics). */ void amdgpu_driver_postclose_kms(struct drm_device *dev, struct drm_file *file_priv) { struct amdgpu_device *adev = dev->dev_private; struct amdgpu_fpriv *fpriv = file_priv->driver_priv; struct amdgpu_bo_list *list; int handle; if (!fpriv) return; pm_runtime_get_sync(dev->dev); amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr); if (adev->asic_type != CHIP_RAVEN) { amdgpu_uvd_free_handles(adev, file_priv); amdgpu_vce_free_handles(adev, file_priv); } amdgpu_vm_bo_rmv(adev, fpriv->prt_va); if (amdgpu_sriov_vf(adev)) { /* TODO: how to handle reserve failure */ BUG_ON(amdgpu_bo_reserve(adev->virt.csa_obj, true)); amdgpu_vm_bo_rmv(adev, fpriv->csa_va); fpriv->csa_va = NULL; amdgpu_bo_unreserve(adev->virt.csa_obj); } amdgpu_vm_fini(adev, &fpriv->vm); idr_for_each_entry(&fpriv->bo_list_handles, list, handle) amdgpu_bo_list_free(list); idr_destroy(&fpriv->bo_list_handles); mutex_destroy(&fpriv->bo_list_lock); kfree(fpriv); file_priv->driver_priv = NULL; pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); }
/** * amdgpu_driver_postclose_kms - drm callback for post close * * @dev: drm dev pointer * @file_priv: drm file * * On device post close, tear down vm on cayman+ (all asics). */ void amdgpu_driver_postclose_kms(struct drm_device *dev, struct drm_file *file_priv) { struct amdgpu_device *adev = dev->dev_private; struct amdgpu_fpriv *fpriv = file_priv->driver_priv; struct amdgpu_bo_list *list; int handle; if (!fpriv) return; amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr); amdgpu_vm_fini(adev, &fpriv->vm); idr_for_each_entry(&fpriv->bo_list_handles, list, handle) amdgpu_bo_list_free(list); idr_destroy(&fpriv->bo_list_handles); mutex_destroy(&fpriv->bo_list_lock); kfree(fpriv); file_priv->driver_priv = NULL; }