From 5a97f2dda4dafab395e15db762a92279fc1c4da2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= <krh@bitplanet.net>
Date: Thu, 17 Jun 2010 15:22:41 -0400
Subject: [PATCH] flink_to

---
 drivers/gpu/drm/drm_auth.c      |    6 +-
 drivers/gpu/drm/drm_fops.c      |    4 ++
 drivers/gpu/drm/i915/i915_drv.h |   14 ++++++
 drivers/gpu/drm/i915/i915_gem.c |   97 +++++++++++++++++++++++++++++++++++++++
 include/drm/drmP.h              |    6 ++
 include/drm/i915_drm.h          |   44 ++++++++++++++++++
 6 files changed, 168 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
index 3f46772..a3c8ed0 100644
--- a/drivers/gpu/drm/drm_auth.c
+++ b/drivers/gpu/drm/drm_auth.c
@@ -45,7 +45,7 @@
  * the one with matching magic number, while holding the drm_device::struct_mutex
  * lock.
  */
-static struct drm_file *drm_find_file(struct drm_master *master, drm_magic_t magic)
+struct drm_file *drm_find_file(struct drm_master *master, drm_magic_t magic)
 {
 	struct drm_file *retval = NULL;
 	struct drm_magic_entry *pt;
@@ -60,6 +60,7 @@ static struct drm_file *drm_find_file(struct drm_master *master, drm_magic_t mag
 	mutex_unlock(&dev->struct_mutex);
 	return retval;
 }
+EXPORT_SYMBOL(drm_find_file);
 
 /**
  * Adds a magic number.
@@ -101,7 +102,7 @@ static int drm_add_magic(struct drm_master *master, struct drm_file *priv,
  * Searches and unlinks the entry in drm_device::magiclist with the magic
  * number hash key, while holding the drm_device::struct_mutex lock.
  */
-static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
+int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
 {
 	struct drm_magic_entry *pt;
 	struct drm_hash_item *hash;
@@ -183,7 +184,6 @@ int drm_authmagic(struct drm_device *dev, void *data,
 	DRM_DEBUG("%u\n", auth->magic);
 	if ((file = drm_find_file(file_priv->master, auth->magic))) {
 		file->authenticated = 1;
-		drm_remove_magic(file_priv->master, auth->magic);
 		return 0;
 	}
 	return -EINVAL;
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index e7aace2..767e02d 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -488,6 +488,10 @@ int drm_release(struct inode *inode, struct file *filp)
 		  (long)old_encode_dev(file_priv->minor->device),
 		  dev->open_count);
 
+	if (file_priv->magic)
+		drm_remove_magic(file_priv->minor->master,
+				 file_priv->magic);
+
 	/* if the master has gone away we can't do anything with the lock */
 	if (file_priv->minor->master)
 		drm_master_release(dev, filp);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9ed8ecd..00b0831 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -124,6 +124,20 @@ struct drm_i915_fence_reg {
 	struct list_head lru_list;
 };
 
+struct drm_i915_gem_name {
+	struct drm_gem_object *obj;
+	u32 name;
+	u32 x;
+	u32 y;
+	u32 width;
+	u32 height;
+	u32 stride;
+	u32 format;
+	u32 tiling_mode;
+	struct list_head list;
+};
+
+
 struct sdvo_device_mapping {
 	u8 dvo_port;
 	u8 slave_addr;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 9ded3da..566d212 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -137,6 +137,103 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
 	return 0;
 }
 
+int
+i915_gem_flink_to_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	struct drm_i915_gem_flink_to *args = data;
+	struct drm_i915_gem_name *name;
+	struct drm_gem_object *obj;
+	struct drm_file *other;
+	int ret;
+
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	if (obj == NULL)
+		return -EBADF;
+
+	other = drm_find_file(file_priv->master, args->magic);
+	name = kmalloc(sizeof *name, GFP_KERNEL);
+	if (name == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	name->obj = obj;
+	name->x = args->x;
+	name->y = args->y;
+	name->width = args->width;
+	name->height = args->height;
+	name->stride = args->stride;
+	name->format = args->format;
+	name->tiling_mode = args->tiling_mode;
+
+again:
+	if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	spin_lock(&dev->object_name_lock);
+	ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
+				&name->name);
+	args->name = (uint64_t) name->name;
+	if (ret == 0)
+		list_add_tail(&name->list, &file_priv->name_list);
+	spin_unlock(&dev->object_name_lock);
+
+	if (ret == -EAGAIN)
+		goto again;
+
+	if (ret != 0)
+		goto err;
+
+	/* Keep the reference for the name table.  */
+	return 0;
+
+err:
+	drm_gem_object_unreference_unlocked(obj);
+	return ret;
+	
+}
+
+int
+i915_gem_open_ioctl(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv)
+{
+	struct drm_i915_gem_open *args = data;
+	struct drm_i915_gem_name *name;
+	int ret;
+
+	spin_lock(&dev->object_name_lock);
+	list_for_each_entry(name, &file_priv->name_list, list)
+		if (args->name == name->name) {
+			list_del(&name->list);
+			idr_remove(&dev->object_name_idr, name->name);
+			break;
+		}
+	spin_unlock(&dev->object_name_lock);
+
+	if (&name->list == &file_priv->name_list)
+		return -ENOENT;
+
+	ret = drm_gem_handle_create(file_priv, name->obj, &args->handle);
+	drm_gem_object_unreference_unlocked(name->obj);
+	if (ret)
+		return ret;
+
+	args->size = name->obj->size;
+	args->x = name->x;
+	args->y = name->y;
+	args->width = name->width;
+	args->height = name->height;
+	args->stride = name->stride;
+	args->format = name->format;
+	args->tiling_mode = name->tiling_mode;
+	kfree(name);
+
+	return 0;
+}
+
 static inline int
 fast_shmem_read(struct page **pages,
 		loff_t page_base, int page_offset,
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index c1b9871..5427173 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -422,6 +422,9 @@ struct drm_file {
 	/** Lock for synchronization of access to object_idr. */
 	spinlock_t table_lock;
 
+	/** List of object names exported from other fpriv's */
+	struct list_head name_list;
+
 	struct file *filp;
 	void *driver_priv;
 
@@ -1225,6 +1228,9 @@ extern struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev,
 extern void drm_drawable_free_all(struct drm_device *dev);
 
 				/* Authentication IOCTL support (drm_auth.h) */
+extern struct drm_file *drm_find_file(struct drm_master *master,
+				      drm_magic_t magic);
+extern int drm_remove_magic(struct drm_master *master, drm_magic_t magic);
 extern int drm_getmagic(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
 extern int drm_authmagic(struct drm_device *dev, void *data,
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 7f0028e..0f641e4 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -189,6 +189,8 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_OVERLAY_PUT_IMAGE	0x27
 #define DRM_I915_OVERLAY_ATTRS	0x28
 #define DRM_I915_GEM_EXECBUFFER2	0x29
+#define DRM_I915_FLINK_TO	0x2a
+#define DRM_I915_OPEN		0x2b
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -229,6 +231,8 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GEM_MADVISE	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)
 #define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE	DRM_IOW(DRM_COMMAND_BASE + DRM_IOCTL_I915_OVERLAY_ATTRS, struct drm_intel_overlay_put_image)
 #define DRM_IOCTL_I915_OVERLAY_ATTRS	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
+#define DRM_IOCTL_I915_GEM_FLINK_TO	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_FLINK_TO, struct drm_i915_gem_flink_to)
+#define DRM_IOCTL_I915_GEM_OPEN		DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OPEN, struct drm_i915_gem_open)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -453,6 +457,46 @@ struct drm_i915_gem_sw_finish {
 	__u32 handle;
 };
 
+struct drm_i915_gem_flink_to {
+	/** Handle for the object being named */
+	__u32 handle;
+
+	/** Magic for destination file_priv */
+	__u32 magic;
+
+	/* FIXME: format? x, y offset? */
+	__u32 x;
+	__u32 y;
+	__u32 width;
+	__u32 height;
+	__u32 stride;
+	__u32 format;
+	__u32 tiling_mode;
+	__u32 swizzle_mode;
+
+	/** Returned name for the object */
+	__u32 name;
+};
+
+struct drm_i915_gem_open {
+	/** Name of object being opened */
+	__u32 name;
+
+	/** Returned handle for the object */
+	__u32 handle;
+
+	/** Returned size of the object */
+	__u32 size;
+	__u32 x;
+	__u32 y;
+	__u32 width;
+	__u32 height;
+	__u32 stride;
+	__u32 format;
+	__u32 tiling_mode;
+	__u32 swizzle_mode;
+};
+
 struct drm_i915_gem_relocation_entry {
 	/**
 	 * Handle of the buffer being pointed to by this relocation entry.
-- 
1.7.1

