summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/msm-hyp/msm_drv_hyp.c147
-rw-r--r--drivers/gpu/drm/msm-hyp/msm_drv_hyp.h15
2 files changed, 154 insertions, 8 deletions
diff --git a/drivers/gpu/drm/msm-hyp/msm_drv_hyp.c b/drivers/gpu/drm/msm-hyp/msm_drv_hyp.c
index 7dd817e41ddd..8e2f57741e43 100644
--- a/drivers/gpu/drm/msm-hyp/msm_drv_hyp.c
+++ b/drivers/gpu/drm/msm-hyp/msm_drv_hyp.c
@@ -81,6 +81,9 @@ static int msm_open(struct drm_device *dev, struct drm_file *file)
if (!ctx)
return -ENOMEM;
+ INIT_LIST_HEAD(&ctx->dmabuf_list);
+ mutex_init(&ctx->dmabuf_lock);
+
file->driver_priv = ctx;
return 0;
@@ -90,6 +93,17 @@ static void msm_preclose(struct drm_device *dev, struct drm_file *file)
{
struct msm_drm_private *priv = dev->dev_private;
struct msm_file_private *ctx = file->driver_priv;
+ struct msm_dmabuf *dmabuf, *pt;
+ struct dma_buf *dma_buf;
+
+ mutex_lock(&ctx->dmabuf_lock);
+ list_for_each_entry_safe(dmabuf, pt, &ctx->dmabuf_list, node) {
+ dma_buf = (struct dma_buf *)dmabuf->dma_id;
+ dma_buf_put(dma_buf);
+ list_del(&dmabuf->node);
+ kfree(dmabuf);
+ }
+ mutex_unlock(&ctx->dmabuf_lock);
mutex_lock(&dev->struct_mutex);
if (ctx == priv->lastctx)
@@ -138,7 +152,24 @@ struct event_req {
u64 user_data;
};
-static size_t msm_drm_write(struct file *filp, const char __user *buffer,
+struct drm_msm_hyp_gem {
+ __u64 handle;
+ __u32 size;
+ __s32 fd;
+};
+
+#define DRM_MSM_HYP_GEM_GET 0x1
+#define DRM_MSM_HYP_GEM_PUT 0x2
+#define DRM_MSM_HYP_GEM_QRY 0x3
+
+#define DRM_IOCTL_MSM_HYP_GEM_GET\
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_HYP_GEM_GET, struct drm_msm_hyp_gem)
+#define DRM_IOCTL_MSM_HYP_GEM_PUT\
+ DRM_IOW(DRM_COMMAND_BASE + DRM_MSM_HYP_GEM_PUT, struct drm_msm_hyp_gem)
+#define DRM_IOCTL_MSM_HYP_GEM_QRY\
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_HYP_GEM_QRY, struct drm_msm_hyp_gem)
+
+static ssize_t msm_drm_write(struct file *filp, const char __user *buffer,
size_t count, loff_t *offset)
{
struct drm_file *file_priv = filp->private_data;
@@ -173,6 +204,108 @@ static size_t msm_drm_write(struct file *filp, const char __user *buffer,
return count;
}
+static int msm_ioctl_gem_get(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_msm_hyp_gem *args = data;
+ struct msm_file_private *ctx = file_priv->driver_priv;
+ struct msm_dmabuf *dmabuf;
+ struct dma_buf *dma_buf;
+ __u64 dma_id;
+ int found = 0;
+ int ret = 0;
+
+ dma_buf = dma_buf_get(args->fd);
+ if (IS_ERR(dma_buf))
+ return PTR_ERR(dma_buf);
+
+ dma_id = (__u64)dma_buf;
+
+ mutex_lock(&ctx->dmabuf_lock);
+ list_for_each_entry(dmabuf, &ctx->dmabuf_list, node) {
+ if (dma_id == dmabuf->dma_id) {
+ args->handle = dmabuf->dma_id;
+ args->size = dma_buf->size;
+ found = 1;
+ break;
+ }
+ }
+ mutex_unlock(&ctx->dmabuf_lock);
+
+ if (found)
+ goto exit;
+
+ dmabuf = kzalloc(sizeof(*dmabuf), GFP_KERNEL);
+ if (!dmabuf) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ dmabuf->dma_id = (__u64)dma_buf;
+
+ mutex_lock(&ctx->dmabuf_lock);
+ list_add(&dmabuf->node, &ctx->dmabuf_list);
+ mutex_unlock(&ctx->dmabuf_lock);
+
+ args->handle = dmabuf->dma_id;
+ args->size = dma_buf->size;
+ return 0;
+
+exit:
+ dma_buf_put(dma_buf);
+ return ret;
+}
+
+static int msm_ioctl_gem_query(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_msm_hyp_gem *args = data;
+ struct msm_file_private *ctx = file_priv->driver_priv;
+ struct msm_dmabuf *dmabuf;
+ struct dma_buf *dma_buf;
+ int ret = -ENOENT;
+
+ args->size = 0;
+ mutex_lock(&ctx->dmabuf_lock);
+ list_for_each_entry(dmabuf, &ctx->dmabuf_list, node) {
+ if (args->handle == dmabuf->dma_id) {
+ dma_buf = (struct dma_buf *)dmabuf->dma_id;
+ if (dma_buf->file)
+ args->size = atomic_long_read(
+ &dma_buf->file->f_count);
+ ret = 0;
+ break;
+ }
+ }
+ mutex_unlock(&ctx->dmabuf_lock);
+
+ return ret;
+}
+
+static int msm_ioctl_gem_put(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_msm_hyp_gem *args = data;
+ struct msm_file_private *ctx = file_priv->driver_priv;
+ struct msm_dmabuf *dmabuf;
+ struct dma_buf *dma_buf;
+ int ret = 0;
+
+ mutex_lock(&ctx->dmabuf_lock);
+ list_for_each_entry(dmabuf, &ctx->dmabuf_list, node) {
+ if (args->handle == dmabuf->dma_id) {
+ dma_buf = (struct dma_buf *)dmabuf->dma_id;
+ dma_buf_put(dma_buf);
+ list_del(&dmabuf->node);
+ kfree(dmabuf);
+ break;
+ }
+ }
+ mutex_unlock(&ctx->dmabuf_lock);
+
+ return ret;
+}
+
static const struct file_operations fops = {
.owner = THIS_MODULE,
.open = drm_open,
@@ -184,6 +317,15 @@ static const struct file_operations fops = {
.llseek = no_llseek,
};
+static const struct drm_ioctl_desc msm_ioctls[] = {
+ DRM_IOCTL_DEF_DRV(MSM_HYP_GEM_GET, msm_ioctl_gem_get,
+ DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(MSM_HYP_GEM_PUT, msm_ioctl_gem_put,
+ DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(MSM_HYP_GEM_QRY, msm_ioctl_gem_query,
+ DRM_AUTH|DRM_RENDER_ALLOW),
+};
+
static struct drm_driver msm_driver = {
.driver_features = 0,
.load = msm_load,
@@ -192,7 +334,8 @@ static struct drm_driver msm_driver = {
.preclose = msm_preclose,
.set_busid = drm_platform_set_busid,
.get_vblank_counter = drm_vblank_no_hw_counter,
- .num_ioctls = 0,
+ .ioctls = msm_ioctls,
+ .num_ioctls = ARRAY_SIZE(msm_ioctls),
.fops = &fops,
.name = "msm_drm_hyp",
.desc = "MSM Snapdragon DRM",
diff --git a/drivers/gpu/drm/msm-hyp/msm_drv_hyp.h b/drivers/gpu/drm/msm-hyp/msm_drv_hyp.h
index affce322ba06..8c8db226bd5b 100644
--- a/drivers/gpu/drm/msm-hyp/msm_drv_hyp.h
+++ b/drivers/gpu/drm/msm-hyp/msm_drv_hyp.h
@@ -28,15 +28,18 @@
#include <linux/slab.h>
#include <linux/sizes.h>
#include <linux/kthread.h>
-
+#include <linux/dma-buf.h>
+#include <linux/atomic.h>
#include <drm/drmP.h>
struct msm_file_private {
- /* currently we don't do anything useful with this.. but when
- * per-context address spaces are supported we'd keep track of
- * the context's page-tables here.
- */
- int dummy;
+ struct list_head dmabuf_list;
+ struct mutex dmabuf_lock;
+};
+
+struct msm_dmabuf {
+ struct list_head node;
+ __u64 dma_id;
};
enum msm_mdp_display_id {