summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/drm_bo.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index 5eb09839..9661b70f 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -306,9 +306,55 @@ int drm_bo_ioctl(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_bo_arg_t arg;
- unsigned long data_ptr;
- (void) dev;
+ drm_bo_arg_request_t *req = &arg.req;
+ drm_bo_arg_reply_t rep;
+ unsigned long next;
+ drm_user_object_t *uo;
+ drm_buffer_object_t *entry;
+
+ do {
+ DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg));
+ rep.ret = 0;
+ rep.handled = 0;
+ switch (req->op) {
+ case drm_bo_destroy:
+ mutex_lock(&dev->struct_mutex);
+ uo = drm_lookup_user_object(priv, req->handle);
+ if (!uo || (uo->type != drm_buffer_type) || uo->owner != priv) {
+ mutex_unlock(&dev->struct_mutex);
+ rep.ret = -EINVAL;
+ break;
+ }
+ rep.ret = drm_remove_user_object(priv, uo);
+ mutex_unlock(&dev->struct_mutex);
+ break;
+ case drm_bo_reference:
+ rep.ret = drm_user_object_ref(priv, req->handle,
+ drm_buffer_type, &uo);
+ if (rep.ret)
+ break;
+ mutex_lock(&dev->struct_mutex);
+ uo = drm_lookup_user_object(priv, req->handle);
+ entry = drm_user_object_entry(uo, drm_buffer_object_t, base);
+ atomic_dec(&entry->usage);
+ mutex_unlock(&dev->struct_mutex);
+ break;
+ case drm_bo_unreference:
+ rep.ret = drm_user_object_unref(priv, req->handle,
+ drm_buffer_type);
+ break;
+ default:
+ rep.ret = -EINVAL;
+ }
+ next = drm_ul(req->next);
+ rep.handled = 1;
+ arg.rep = rep;
+ DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg));
+ data = next;
+
+ } while (data);
return 0;
+
}