int ttm_pl_reference_ioctl(struct ttm_object_file *tfile, void *data)
{
	union ttm_pl_reference_arg *arg = data;
	struct ttm_pl_rep *rep = &arg->rep;
	struct ttm_bo_user_object *user_bo;
	struct ttm_buffer_object *bo;
	struct ttm_base_object *base;
	int ret;

	user_bo = ttm_bo_user_lookup(tfile, arg->req.handle);
	if (unlikely(user_bo == NULL)) {
		printk(KERN_ERR "Could not reference buffer object.\n");
		return -EINVAL;
	}

	bo = &user_bo->bo;
	ret = ttm_ref_object_add(tfile, &user_bo->base, TTM_REF_USAGE, NULL);
	if (unlikely(ret != 0)) {
		printk(KERN_ERR
		       "Could not add a reference to buffer object.\n");
		goto out;
	}

	ret = ttm_bo_reserve(bo, true, false, false, 0);
	if (unlikely(ret != 0))
		goto out;
	ttm_pl_fill_rep(bo, rep);
	ttm_bo_unreserve(bo);

out:
	base = &user_bo->base;
	ttm_base_object_unref(&base);
	return ret;
}
int ttm_pl_synccpu_ioctl(struct ttm_object_file *tfile, void *data)
{
	struct ttm_pl_synccpu_arg *arg = data;
	struct ttm_bo_user_object *user_bo;
	struct ttm_buffer_object *bo;
	struct ttm_base_object *base;
	bool existed;
	int ret;

	switch (arg->op) {
	case TTM_PL_SYNCCPU_OP_GRAB:
		user_bo = ttm_bo_user_lookup(tfile, arg->handle);
		if (unlikely(user_bo == NULL)) {
			printk(KERN_ERR
			       "Could not find buffer object for synccpu.\n");
			return -EINVAL;
		}
		bo = &user_bo->bo;
		base = &user_bo->base;
		ret = ttm_bo_synccpu_write_grab(bo,
						arg->access_mode &
						TTM_PL_SYNCCPU_MODE_NO_BLOCK);
		if (unlikely(ret != 0)) {
			ttm_base_object_unref(&base);
			goto out;
		}
		ret = ttm_ref_object_add(tfile, &user_bo->base,
					 TTM_REF_SYNCCPU_WRITE, &existed);
		if (existed || ret != 0)
			ttm_bo_synccpu_write_release(bo);
		ttm_base_object_unref(&base);
		break;
	case TTM_PL_SYNCCPU_OP_RELEASE:
		ret = ttm_ref_object_base_unref(tfile, arg->handle,
						TTM_REF_SYNCCPU_WRITE);
		break;
	default:
		ret = -EINVAL;
		break;
	}
out:
	return ret;
}
struct ttm_buffer_object *ttm_buffer_object_lookup(struct ttm_object_file
		*tfile, uint32_t handle) {
	struct ttm_bo_user_object *user_bo;
	struct ttm_base_object *base;

	user_bo = ttm_bo_user_lookup(tfile, handle);
	if (unlikely(user_bo == NULL))
		return NULL;

	(void)ttm_bo_reference(&user_bo->bo);
	base = &user_bo->base;
	ttm_base_object_unref(&base);
	return &user_bo->bo;
}
static struct ttm_bo_user_object *ttm_bo_user_lookup(struct ttm_object_file
		*tfile, uint32_t handle) {
	struct ttm_base_object *base;

	base = ttm_base_object_lookup(tfile, handle);
	if (unlikely(base == NULL)) {
		printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
		       (unsigned long)handle);
		return NULL;
	}

	if (unlikely(base->object_type != ttm_buffer_type)) {
		ttm_base_object_unref(&base);
		printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
		       (unsigned long)handle);
		return NULL;
	}

	return container_of(base, struct ttm_bo_user_object, base);
}
Esempio n. 5
0
int ttm_base_object_init(struct ttm_object_file *tfile,
			 struct ttm_base_object *base,
			 bool shareable,
			 enum ttm_object_type object_type,
			 void (*rcount_release) (struct ttm_base_object **),
			 void (*ref_obj_release) (struct ttm_base_object *,
						  enum ttm_ref_type ref_type))
{
	struct ttm_object_device *tdev = tfile->tdev;
	int ret;

	base->shareable = shareable;
	base->tfile = ttm_object_file_ref(tfile);
	base->refcount_release = rcount_release;
	base->ref_obj_release = ref_obj_release;
	base->object_type = object_type;
	refcount_init(&base->refcount, 1);
	rw_init(&tdev->object_lock, "ttmbao");
	rw_wlock(&tdev->object_lock);
	ret = drm_ht_just_insert_please(&tdev->object_hash,
					    &base->hash,
					    (unsigned long)base, 31, 0, 0);
	rw_wunlock(&tdev->object_lock);
	if (unlikely(ret != 0))
		goto out_err0;

	ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL);
	if (unlikely(ret != 0))
		goto out_err1;

	ttm_base_object_unref(&base);

	return 0;
out_err1:
	rw_wlock(&tdev->object_lock);
	(void)drm_ht_remove_item(&tdev->object_hash, &base->hash);
	rw_wunlock(&tdev->object_lock);
out_err0:
	return ret;
}
/**
 * vmw_simple_resource_create_ioctl - Helper to set up an ioctl function to
 * create a struct vmw_simple_resource.
 *
 * @dev: Pointer to a struct drm device.
 * @data: Ioctl argument.
 * @file_priv: Pointer to a struct drm_file identifying the caller.
 * @func: Pointer to a struct vmw_simple_resource_func identifying the
 * simple resource type.
 *
 * Returns:
 *   0 if success,
 *   Negative error value on error.
 */
int
vmw_simple_resource_create_ioctl(struct drm_device *dev, void *data,
				 struct drm_file *file_priv,
				 const struct vmw_simple_resource_func *func)
{
	struct vmw_private *dev_priv = vmw_priv(dev);
	struct vmw_user_simple_resource *usimple;
	struct vmw_resource *res;
	struct vmw_resource *tmp;
	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
	struct ttm_operation_ctx ctx = {
		.interruptible = true,
		.no_wait_gpu = false
	};
	size_t alloc_size;
	size_t account_size;
	int ret;

	alloc_size = offsetof(struct vmw_user_simple_resource, simple) +
	  func->size;
	account_size = ttm_round_pot(alloc_size) + VMW_IDA_ACC_SIZE +
		TTM_OBJ_EXTRA_SIZE;

	ret = ttm_read_lock(&dev_priv->reservation_sem, true);
	if (ret)
		return ret;

	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), account_size,
				   &ctx);
	ttm_read_unlock(&dev_priv->reservation_sem);
	if (ret) {
		if (ret != -ERESTARTSYS)
			DRM_ERROR("Out of graphics memory for %s"
				  " creation.\n", func->res_func.type_name);

		goto out_ret;
	}

	usimple = kzalloc(alloc_size, GFP_KERNEL);
	if (!usimple) {
		ttm_mem_global_free(vmw_mem_glob(dev_priv),
				    account_size);
		ret = -ENOMEM;
		goto out_ret;
	}

	usimple->simple.func = func;
	usimple->account_size = account_size;
	res = &usimple->simple.res;
	usimple->base.shareable = false;
	usimple->base.tfile = NULL;

	/*
	 * From here on, the destructor takes over resource freeing.
	 */
	ret = vmw_simple_resource_init(dev_priv, &usimple->simple,
				       data, vmw_simple_resource_free);
	if (ret)
		goto out_ret;

	tmp = vmw_resource_reference(res);
	ret = ttm_base_object_init(tfile, &usimple->base, false,
				   func->ttm_res_type,
				   &vmw_simple_resource_base_release, NULL);

	if (ret) {
		vmw_resource_unreference(&tmp);
		goto out_err;
	}

	func->set_arg_handle(data, usimple->base.handle);
out_err:
	vmw_resource_unreference(&res);
out_ret:
	return ret;
}

/**
 * vmw_simple_resource_lookup - Look up a simple resource from its user-space
 * handle.
 *
 * @tfile: struct ttm_object_file identifying the caller.
 * @handle: The user-space handle.
 * @func: The struct vmw_simple_resource_func identifying the simple resource
 * type.
 *
 * Returns: Refcounted pointer to the embedded struct vmw_resource if
 * successfule. Error pointer otherwise.
 */
struct vmw_resource *
vmw_simple_resource_lookup(struct ttm_object_file *tfile,
			   uint32_t handle,
			   const struct vmw_simple_resource_func *func)
{
	struct vmw_user_simple_resource *usimple;
	struct ttm_base_object *base;
	struct vmw_resource *res;

	base = ttm_base_object_lookup(tfile, handle);
	if (!base) {
		DRM_ERROR("Invalid %s handle 0x%08lx.\n",
			  func->res_func.type_name,
			  (unsigned long) handle);
		return ERR_PTR(-ESRCH);
	}

	if (ttm_base_object_type(base) != func->ttm_res_type) {
		ttm_base_object_unref(&base);
		DRM_ERROR("Invalid type of %s handle 0x%08lx.\n",
			  func->res_func.type_name,
			  (unsigned long) handle);
		return ERR_PTR(-EINVAL);
	}

	usimple = container_of(base, typeof(*usimple), base);
	res = vmw_resource_reference(&usimple->simple.res);
	ttm_base_object_unref(&base);

	return res;
}