summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2017-06-15 16:10:57 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-06-15 16:10:56 -0700
commit68717de447daa7446d408f44210ae94bbc07ed61 (patch)
tree921927299fc72ac7d0b5f603ed824206a1a6e12c /drivers/gpu
parent63c0d4a4b670368c4e5f953616d1a6535658b05e (diff)
parent7d46546d28250cb7a5404dee299694ac421f20de (diff)
Merge "drm/msm: Add per-instance submit queues"
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/msm/Makefile3
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c48
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h13
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h5
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c17
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h15
-rw-r--r--drivers/gpu/drm/msm/msm_submitqueue.c125
7 files changed, 216 insertions, 10 deletions
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index f3a8a8416c7a..c916626c8329 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -144,6 +144,7 @@ msm_drm-$(CONFIG_DRM_MSM) += \
msm_rd.o \
msm_ringbuffer.o \
msm_prop.o \
- msm_snapshot.o
+ msm_snapshot.o \
+ msm_submitqueue.o
obj-$(CONFIG_DRM_MSM) += msm_drm.o
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index a3bdc30b9620..02a20462121d 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -604,6 +604,8 @@ static int msm_open(struct drm_device *dev, struct drm_file *file)
INIT_LIST_HEAD(&ctx->counters);
+ msm_submitqueue_init(ctx);
+
file->driver_priv = ctx;
kms = priv->kms;
@@ -632,12 +634,18 @@ static void msm_postclose(struct drm_device *dev, struct drm_file *file)
if (kms && kms->funcs && kms->funcs->postclose)
kms->funcs->postclose(kms, file);
- if (priv->gpu)
+ if (!ctx)
+ return;
+
+ msm_submitqueue_close(ctx);
+
+ if (priv->gpu) {
msm_gpu_cleanup_counters(priv->gpu, ctx);
- if (ctx && ctx->aspace && ctx->aspace != priv->gpu->aspace) {
- ctx->aspace->mmu->funcs->detach(ctx->aspace->mmu);
- msm_gem_address_space_put(ctx->aspace);
+ if (ctx->aspace && ctx->aspace != priv->gpu->aspace) {
+ ctx->aspace->mmu->funcs->detach(ctx->aspace->mmu);
+ msm_gem_address_space_put(ctx->aspace);
+ }
}
kfree(ctx);
@@ -1683,6 +1691,34 @@ static int msm_ioctl_counter_read(struct drm_device *dev, void *data,
return -ENODEV;
}
+
+static int msm_ioctl_submitqueue_new(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_msm_submitqueue *args = data;
+ struct msm_drm_private *priv = dev->dev_private;
+ struct msm_gpu *gpu = priv->gpu;
+
+ if (args->flags & ~MSM_SUBMITQUEUE_FLAGS)
+ return -EINVAL;
+
+ if (!file->is_master && args->prio >= gpu->nr_rings - 1) {
+ DRM_ERROR("Only DRM master can set highest priority ringbuffer\n");
+ return -EPERM;
+ }
+
+ return msm_submitqueue_create(file->driver_priv, args->prio,
+ args->flags, &args->id);
+}
+
+static int msm_ioctl_submitqueue_close(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_msm_submitqueue *args = data;
+
+ return msm_submitqueue_remove(file->driver_priv, args->id);
+}
+
int msm_release(struct inode *inode, struct file *filp)
{
struct drm_file *file_priv = filp->private_data;
@@ -1728,6 +1764,10 @@ static const struct drm_ioctl_desc msm_ioctls[] = {
DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(MSM_GEM_SVM_NEW, msm_ioctl_gem_svm_new,
DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_NEW, msm_ioctl_submitqueue_new,
+ DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_CLOSE, msm_ioctl_submitqueue_close,
+ DRM_AUTH|DRM_RENDER_ALLOW),
};
static const struct vm_operations_struct vm_ops = {
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 408e05158827..660c608b64f0 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -78,6 +78,9 @@ struct msm_gem_vma;
struct msm_file_private {
struct msm_gem_address_space *aspace;
struct list_head counters;
+ rwlock_t queuelock;
+ struct list_head submitqueues;
+ int queueid;
};
enum msm_mdp_plane_property {
@@ -507,6 +510,16 @@ struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,
struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev);
+struct msm_gpu_submitqueue;
+int msm_submitqueue_init(struct msm_file_private *ctx);
+struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx,
+ u32 id);
+int msm_submitqueue_create(struct msm_file_private *ctx, u32 prio,
+ u32 flags, u32 *id);
+int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id);
+void msm_submitqueue_close(struct msm_file_private *ctx);
+void msm_submitqueue_destroy(struct kref *kref);
+
struct hdmi;
int hdmi_modeset_init(struct hdmi *hdmi, struct drm_device *dev,
struct drm_encoder *encoder);
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index 9d657465c7bb..e8528892939f 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -132,6 +132,9 @@ static inline uint32_t msm_gem_fence(struct msm_gem_object *msm_obj,
return fence;
}
+/* Internal submit flags */
+#define SUBMIT_FLAG_SKIP_HANGCHECK 0x00000001
+
/* Created per submit-ioctl, to track bo's and cmdstream bufs, etc,
* associated with the cmdstream submission for synchronization (and
* make it easier to unwind when things go wrong, etc). This only
@@ -145,10 +148,12 @@ struct msm_gem_submit {
struct ww_acquire_ctx ticket;
uint32_t fence;
int ring;
+ u32 flags;
bool valid;
uint64_t profile_buf_iova;
void *profile_buf_vaddr;
bool secure;
+ struct msm_gpu_submitqueue *queue;
unsigned int nr_cmds;
unsigned int nr_bos;
struct {
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 4f40aee1a80b..b9ace0d9e69b 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -35,7 +35,8 @@ static inline void __user *to_user_ptr(u64 address)
static struct msm_gem_submit *submit_create(struct drm_device *dev,
struct msm_gem_address_space *aspace,
- uint32_t nr_bos, uint32_t nr_cmds)
+ uint32_t nr_bos, uint32_t nr_cmds,
+ struct msm_gpu_submitqueue *queue)
{
struct msm_gem_submit *submit;
uint64_t sz = sizeof(*submit) + (nr_bos * sizeof(submit->bos[0])) +
@@ -48,6 +49,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,
if (submit) {
submit->dev = dev;
submit->aspace = aspace;
+ submit->queue = queue;
/* initially, until copy_from_user() and bo lookup succeeds: */
submit->nr_bos = 0;
@@ -84,6 +86,7 @@ void msm_gem_submit_free(struct msm_gem_submit *submit)
if (!submit)
return;
+ msm_submitqueue_put(submit->queue);
list_del(&submit->node);
kfree(submit);
}
@@ -415,6 +418,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
struct drm_msm_gem_submit *args = data;
struct msm_file_private *ctx = file->driver_priv;
struct msm_gem_submit *submit;
+ struct msm_gpu_submitqueue *queue;
struct msm_gpu *gpu;
unsigned i;
int ret;
@@ -429,9 +433,14 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
if (!gpu)
return -ENXIO;
+ queue = msm_submitqueue_get(ctx, args->queueid);
+ if (!queue)
+ return -ENOENT;
+
mutex_lock(&dev->struct_mutex);
- submit = submit_create(dev, ctx->aspace, args->nr_bos, args->nr_cmds);
+ submit = submit_create(dev, ctx->aspace, args->nr_bos, args->nr_cmds,
+ queue);
if (!submit) {
ret = -ENOMEM;
goto out;
@@ -518,9 +527,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
submit->nr_cmds = i;
/* Clamp the user submitted ring to the range of available rings */
- submit->ring = clamp_t(uint32_t,
- (args->flags & MSM_SUBMIT_RING_MASK) >> MSM_SUBMIT_RING_SHIFT,
- 0, gpu->nr_rings - 1);
+ submit->ring = clamp_t(uint32_t, queue->prio, 0, gpu->nr_rings - 1);
ret = msm_gpu_submit(gpu, submit);
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index d3b683dfe143..cddbcbbb8557 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -150,6 +150,15 @@ struct msm_gpu {
struct msm_snapshot *snapshot;
};
+struct msm_gpu_submitqueue {
+ int id;
+ u32 flags;
+ u32 prio;
+ int faults;
+ struct list_head node;
+ struct kref ref;
+};
+
/* It turns out that all targets use the same ringbuffer size. */
#define MSM_GPU_RINGBUFFER_SZ SZ_32K
#define MSM_GPU_RINGBUFFER_BLKSIZE 32
@@ -277,4 +286,10 @@ void msm_gpu_cleanup_counters(struct msm_gpu *gpu,
u64 msm_gpu_counter_read(struct msm_gpu *gpu,
struct drm_msm_counter_read *data);
+static inline void msm_submitqueue_put(struct msm_gpu_submitqueue *queue)
+{
+ if (queue)
+ kref_put(&queue->ref, msm_submitqueue_destroy);
+}
+
#endif /* __MSM_GPU_H__ */
diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c
new file mode 100644
index 000000000000..8e29021bb0d8
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_submitqueue.c
@@ -0,0 +1,125 @@
+/* Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kref.h>
+#include "msm_gpu.h"
+
+void msm_submitqueue_destroy(struct kref *kref)
+{
+ struct msm_gpu_submitqueue *queue = container_of(kref,
+ struct msm_gpu_submitqueue, ref);
+
+ kfree(queue);
+}
+
+struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx,
+ u32 id)
+{
+ struct msm_gpu_submitqueue *entry;
+
+ read_lock(&ctx->queuelock);
+
+ list_for_each_entry(entry, &ctx->submitqueues, node) {
+ if (entry->id == id) {
+ kref_get(&entry->ref);
+ read_unlock(&ctx->queuelock);
+
+ return entry;
+ }
+ }
+
+ read_unlock(&ctx->queuelock);
+ return NULL;
+}
+
+void msm_submitqueue_close(struct msm_file_private *ctx)
+{
+ struct msm_gpu_submitqueue *entry, *tmp;
+
+ /*
+ * No lock needed in close and there won't
+ * be any more user ioctls coming our way
+ */
+
+ list_for_each_entry_safe(entry, tmp, &ctx->submitqueues, node)
+ msm_submitqueue_put(entry);
+}
+
+int msm_submitqueue_create(struct msm_file_private *ctx, u32 prio, u32 flags,
+ u32 *id)
+{
+ struct msm_gpu_submitqueue *queue = kzalloc(sizeof(*queue), GFP_KERNEL);
+
+ if (!queue)
+ return -ENOMEM;
+
+ kref_init(&queue->ref);
+ queue->flags = flags;
+ queue->prio = prio;
+
+ write_lock(&ctx->queuelock);
+
+ queue->id = ctx->queueid++;
+
+ if (id)
+ *id = queue->id;
+
+ list_add_tail(&queue->node, &ctx->submitqueues);
+
+ write_unlock(&ctx->queuelock);
+
+ return 0;
+}
+
+int msm_submitqueue_init(struct msm_file_private *ctx)
+{
+ INIT_LIST_HEAD(&ctx->submitqueues);
+
+ rwlock_init(&ctx->queuelock);
+
+ /*
+ * Add the "default" submitqueue with id 0
+ * "medium" priority (3) and no flags
+ */
+
+ return msm_submitqueue_create(ctx, 3, 0, NULL);
+}
+
+int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id)
+{
+ struct msm_gpu_submitqueue *entry;
+
+ /*
+ * id 0 is the "default" queue and can't be destroyed
+ * by the user
+ */
+
+ if (!id)
+ return -ENOENT;
+
+ write_lock(&ctx->queuelock);
+
+ list_for_each_entry(entry, &ctx->submitqueues, node) {
+ if (entry->id == id) {
+ list_del(&entry->node);
+ write_unlock(&ctx->queuelock);
+
+ msm_submitqueue_put(entry);
+ return 0;
+ }
+ }
+
+ write_unlock(&ctx->queuelock);
+ return -ENOENT;
+}
+