summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/drm_bo.c46
-rw-r--r--shared-core/drm.h4
2 files changed, 45 insertions, 5 deletions
diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index affee135..7f5088fb 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -507,11 +507,14 @@ static int drm_buffer_object_unmap(drm_file_t *priv, uint32_t handle)
* Call struct-sem locked.
*/
-static void drm_buffer_user_object_unmap(drm_file_t *priv, drm_user_object_t *uo)
+static void drm_buffer_user_object_unmap(drm_file_t *priv, drm_user_object_t *uo,
+ drm_ref_t action)
{
drm_device_t *dev = priv->head->dev;
drm_buffer_object_t *bo = drm_user_object_entry(uo, drm_buffer_object_t, base);
+ BUG_ON(action != _DRM_REF_TYPE1);
+
if (atomic_dec_and_test(&bo->mapped)) {
mutex_unlock(&dev->struct_mutex);
mutex_lock(&bo->mutex);
@@ -534,7 +537,7 @@ int drm_buffer_object_create(drm_file_t *priv,
uint32_t ttm_handle,
uint32_t mask,
uint32_t hint,
- void __user *user_pages,
+ unsigned long buffer_start,
drm_buffer_object_t **buf_obj)
{
drm_device_t *dev = priv->head->dev;
@@ -569,7 +572,7 @@ int drm_buffer_object_create(drm_file_t *priv,
goto out_err;
break;
case drm_bo_type_user:
- bo->user_pages = user_pages;
+ bo->user_pages = (void __user *)buffer_start;
break;
default:
ret = -EINVAL;
@@ -592,6 +595,27 @@ int drm_buffer_object_create(drm_file_t *priv,
drm_free(bo, sizeof(*bo), DRM_MEM_BUFOBJ);
return ret;
}
+
+static int drm_bo_add_user_object(drm_file_t *priv, drm_buffer_object_t *bo,
+ int shareable)
+{
+ drm_device_t *dev = priv->head->dev;
+ int ret;
+
+ mutex_lock(&dev->struct_mutex);
+ ret = drm_add_user_object(priv, &bo->base, shareable);
+ if (ret)
+ goto out;
+
+ bo->base.remove = drm_bo_base_deref_locked;
+ bo->base.type = drm_buffer_type;
+ bo->base.ref_struct_locked = NULL;
+ bo->base.unref = drm_buffer_user_object_unmap;
+
+ out:
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+}
@@ -610,6 +634,22 @@ int drm_bo_ioctl(DRM_IOCTL_ARGS)
rep.ret = 0;
rep.handled = 0;
switch (req->op) {
+ case drm_bo_create: {
+ unsigned long buffer_start = drm_ul(req->buffer_start);
+ rep.ret = drm_buffer_object_create(priv, drm_ul(req->size),
+ req->type, req->arg_handle,
+ req->mask, req->hint,
+ buffer_start,
+ &entry);
+ if (rep.ret)
+ break;
+
+ rep.ret = drm_bo_add_user_object(priv, entry, req->mask &
+ DRM_BO_FLAG_SHAREABLE);
+ if (rep.ret)
+ drm_bo_usage_deref_unlocked(dev, entry);
+ break;
+ }
case drm_bo_unmap:
rep.ret = drm_buffer_object_unmap(priv, req->handle);
break;
diff --git a/shared-core/drm.h b/shared-core/drm.h
index 14b1741f..d03eebcb 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -684,7 +684,7 @@ typedef struct drm_ttm_arg {
#define DRM_BO_FLAG_SHADOW_VRAM 0x00000020
#define DRM_BO_FLAG_READ_LOCAL 0x00000040
#define DRM_BO_FLAG_UNCACHED 0x00000080
-
+#define DRM_BO_FLAG_SHAREABLE 0x00000100
#define DRM_BO_FLAG_MEM_TT 0x01000000
#define DRM_BO_FLAG_MEM_VRAM 0x02000000
@@ -709,7 +709,7 @@ typedef struct drm_bo_arg_request {
drm_u64_t size;
drm_bo_type_t type;
unsigned arg_handle;
- drm_u64_t user_pointer;
+ drm_u64_t buffer_start;
drm_u64_t next;
enum {
drm_bo_create,