summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/drm_bo.c63
-rw-r--r--linux-core/drm_ttm.c2
-rw-r--r--linux-core/drm_ttm.h3
-rw-r--r--shared-core/drm.h8
4 files changed, 63 insertions, 13 deletions
diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index 6a677578..847b0406 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -31,6 +31,30 @@
#include "drmP.h"
+/*
+ * Buffer object locking policy:
+ * Lock dev->struct_mutex;
+ * Increase usage
+ * Unlock dev->struct_mutex;
+ * Lock buffer->mutex;
+ * Do whatever you want;
+ * Unlock buffer->mutex;
+ * Decrease usage. Call destruction if zero.
+ *
+ * User object visibility ups usage just once, since it has its own
+ * refcounting.
+ *
+ * Destruction:
+ * lock dev->struct_mutex;
+ * Verify that usage is zero. Otherwise unlock and continue.
+ * Destroy object.
+ * unlock dev->struct_mutex;
+ *
+ * Mutex and spinlock locking orders:
+ * 1.) Buffer mutex
+ * 2.) Refer to ttm locking orders.
+ */
+
int drm_fence_buffer_objects(drm_file_t *priv)
{
drm_device_t *dev = priv->head->dev;
@@ -277,11 +301,35 @@ int drm_bo_alloc_space(drm_device_t *dev, int tt, drm_buffer_object_t *buf)
}
#endif
-static int drm_do_bo_ioctl(drm_file_t *priv, int num_requests, void __user *data)
+static int drm_do_bo_ioctl(drm_file_t *priv, int num_requests,
+ drm_bo_arg_data_t __user *data)
{
- return 0;
+ drm_bo_arg_data_t arg;
+ drm_bo_arg_request_t *req = &arg.req;
+ drm_bo_arg_reply_t rep;
+ int i, ret;
+
+ for (i=0; i<num_requests; ++i) {
+ rep.ret = 0;
+ ret = copy_from_user(&arg, (void __user *) data, sizeof(arg));
+ if (ret) {
+ rep.ret = -EFAULT;
+ goto out_loop;
+ }
+
+ arg.rep = rep;
+ data++;
+ out_loop:
+ arg.rep = rep;
+ ret = copy_to_user((void __user *) data, &arg, sizeof(arg));
+ if (!ret)
+ ++i;
+ break;
+ }
+ return i;
}
+
int drm_bo_ioctl(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
@@ -299,13 +347,16 @@ int drm_bo_ioctl(DRM_IOCTL_ARGS)
switch(arg.op) {
case drm_op_bo:
- return drm_do_bo_ioctl(priv, arg.num_requests,
- (void __user *) data_ptr);
+ arg.num_requests = drm_do_bo_ioctl(priv, arg.num_requests,
+ (drm_bo_arg_data_t __user *)
+ data_ptr);
+ break;
case drm_op_ttm:
- return drm_ttm_ioctl(priv, arg.num_requests,
- (drm_ttm_arg_t __user *) data_ptr);
+ return drm_ttm_ioctl(priv, (drm_ttm_arg_t __user *)
+ data_ptr);
}
+ DRM_COPY_TO_USER_IOCTL((void __user *) data, arg, sizeof(arg));
return 0;
}
diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c
index 46878a7d..05bae7de 100644
--- a/linux-core/drm_ttm.c
+++ b/linux-core/drm_ttm.c
@@ -799,7 +799,7 @@ int drm_add_ttm(drm_device_t * dev, unsigned size, drm_map_list_t ** maplist)
return 0;
}
-int drm_ttm_ioctl(drm_file_t *priv, int num_requests, drm_ttm_arg_t __user *data)
+int drm_ttm_ioctl(drm_file_t *priv, drm_ttm_arg_t __user *data)
{
return 0;
}
diff --git a/linux-core/drm_ttm.h b/linux-core/drm_ttm.h
index 81006c3c..5a7569ff 100644
--- a/linux-core/drm_ttm.h
+++ b/linux-core/drm_ttm.h
@@ -148,8 +148,7 @@ extern int drm_destroy_ttm(drm_ttm_t * ttm);
extern void drm_user_destroy_region(drm_ttm_backend_list_t * entry);
extern int drm_ttm_add_mm_to_list(drm_ttm_t * ttm, struct mm_struct *mm);
extern void drm_ttm_delete_mm(drm_ttm_t * ttm, struct mm_struct *mm);
-extern int drm_ttm_ioctl(drm_file_t *priv, int num_requests,
- drm_ttm_arg_t __user *data);
+extern int drm_ttm_ioctl(drm_file_t *priv, drm_ttm_arg_t __user *data);
#define DRM_MASK_VAL(dest, mask, val) \
(dest) = ((dest) & ~(mask)) | ((val) & (mask));
diff --git a/shared-core/drm.h b/shared-core/drm.h
index fb18b5c5..feadfc67 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -740,10 +740,10 @@ typedef struct drm_bo_arg_reply {
}drm_bo_arg_reply_t;
-typedef union {
- drm_bo_arg_request_t bo_req;
- drm_bo_arg_reply_t bo_rep;
-}drm_bo_arg_data;
+typedef union drm_bo_arg_data {
+ drm_bo_arg_request_t req;
+ drm_bo_arg_reply_t rep;
+} drm_bo_arg_data_t;
/**