History

drm/msm: Add per-instance submit queues

Currently the behavior of a command stream is provided by the user application during submission and the application is expected to internally maintain the settings for each 'context' or 'rendering queue' and specify the correct ones. This works okay for simple cases but as applications become more complex we will want to set context specific flags and do various permission checks to allow certain contexts to enable additional privileges. Add kernel-side submit queues to be analogous to 'contexts' or 'rendering queues' on the application side. Each file descriptor instance will maintain its own list of queues. Queues cannot be shared between file descriptors. For backwards compatibility context id '0' is defined as a default context specifying no priority and no special flags. This is intended to be the usual configuration for 99% of applications so that a garden variety application can function correctly without creating a queue. Only those applications requiring the specific benefit of different queues need create one.

Jordan Crouse committed 9 years ago

Commit f7de1541 parent 0033e1b8 files · +250 −16Browse files

Unified · Split

8 files
  1. drivers/gpu/drm/msm/Makefile +2 −1
  2. drivers/gpu/drm/msm/msm_drv.c +48 −8
  3. drivers/gpu/drm/msm/msm_drv.h +15 −5
  4. drivers/gpu/drm/msm/msm_gem.h +1 −0
  5. drivers/gpu/drm/msm/msm_gem_submit.c +12 −2
  6. drivers/gpu/drm/msm/msm_gpu.h +15 −0
  7. drivers/gpu/drm/msm/msm_submitqueue.c +135 −0
  8. include/uapi/drm/msm_drm.h +22 −0
drivers/gpu/drm/msm/Makefile+2−1
@@ -57,7 +57,8 @@ msm-y := \ · 56 unmodified lines
5757 msm_iommu.o \
5858 msm_perf.o \
5959 msm_rd.o \
60− msm_ringbuffer.o
60+ msm_ringbuffer.o \
61+ msm_submitqueue.o
6162
6263 msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o
6364 msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o
drivers/gpu/drm/msm/msm_drv.c+48−8
@@ -29,9 +29,12 @@ · 28 unmodified lines
2929 * - 1.0.0 - initial interface
3030 * - 1.1.0 - adds madvise, and support for submits with > 4 cmd buffers
3131 * - 1.2.0 - adds explicit fence support for submit ioctl
32+ * - 1.3.0 - adds GMEM_BASE + NR_RINGS params, SUBMITQUEUE_NEW +
33+ * SUBMITQUEUE_CLOSE ioctls, and MSM_INFO_IOVA flag for
34+ * MSM_GEM_INFO ioctl.
3235 */
3336 #define MSM_VERSION_MAJOR 1
34−#define MSM_VERSION_MINOR 2
37+#define MSM_VERSION_MINOR 3
3538 #define MSM_VERSION_PATCHLEVEL 0
3639
3740 static void msm_fb_output_poll_changed(struct drm_device *dev)
@@ -504,24 +507,37 @@ static void load_gpu(struct drm_device *dev) · 466 unmodified lines
504507 mutex_unlock(&init_lock);
505508 }
506509
507−static int msm_open(struct drm_device *dev, struct drm_file *file)
510+static int context_init(struct drm_file *file)
508511 {
509512 struct msm_file_private *ctx;
510513
511− /* For now, load gpu on open.. to avoid the requirement of having
512− * firmware in the initrd.
513− */
514− load_gpu(dev);
515−
516514 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
517515 if (!ctx)
518516 return -ENOMEM;
519517
518+ msm_submitqueue_init(ctx);
519+
520520 file->driver_priv = ctx;
521521
522522 return 0;
523523 }
524524
525+static int msm_open(struct drm_device *dev, struct drm_file *file)
526+{
527+ /* For now, load gpu on open.. to avoid the requirement of having
528+ * firmware in the initrd.
529+ */
530+ load_gpu(dev);
531+
532+ return context_init(file);
533+}
534+
535+static void context_close(struct msm_file_private *ctx)
536+{
537+ msm_submitqueue_close(ctx);
538+ kfree(ctx);
539+}
540+
525541 static void msm_postclose(struct drm_device *dev, struct drm_file *file)
526542 {
527543 struct msm_drm_private *priv = dev->dev_private;
@@ -532,7 +548,7 @@ static void msm_postclose(struct drm_device *dev, struct drm_file *file) · 4 unmodified lines
532548 priv->lastctx = NULL;
533549 mutex_unlock(&dev->struct_mutex);
534550
535− kfree(ctx);
551+ context_close(ctx);
536552 }
537553
538554 static void msm_lastclose(struct drm_device *dev)
@@ -777,6 +793,28 @@ unlock: · 238 unmodified lines
777793 return ret;
778794 }
779795
796+
797+static int msm_ioctl_submitqueue_new(struct drm_device *dev, void *data,
798+ struct drm_file *file)
799+{
800+ struct drm_msm_submitqueue *args = data;
801+
802+ if (args->flags & ~MSM_SUBMITQUEUE_FLAGS)
803+ return -EINVAL;
804+
805+ return msm_submitqueue_create(file->driver_priv, args->prio,
806+ args->flags, &args->id);
807+}
808+
809+
810+static int msm_ioctl_submitqueue_close(struct drm_device *dev, void *data,
811+ struct drm_file *file)
812+{
813+ u32 id = *(u32 *) data;
814+
815+ return msm_submitqueue_remove(file->driver_priv, id);
816+}
817+
780818 static const struct drm_ioctl_desc msm_ioctls[] = {
781819 DRM_IOCTL_DEF_DRV(MSM_GET_PARAM, msm_ioctl_get_param, DRM_AUTH|DRM_RENDER_ALLOW),
782820 DRM_IOCTL_DEF_DRV(MSM_GEM_NEW, msm_ioctl_gem_new, DRM_AUTH|DRM_RENDER_ALLOW),
@@ -786,6 +824,8 @@ static const struct drm_ioctl_desc msm_ioctls[] = { · 3 unmodified lines
786824 DRM_IOCTL_DEF_DRV(MSM_GEM_SUBMIT, msm_ioctl_gem_submit, DRM_AUTH|DRM_RENDER_ALLOW),
787825 DRM_IOCTL_DEF_DRV(MSM_WAIT_FENCE, msm_ioctl_wait_fence, DRM_AUTH|DRM_RENDER_ALLOW),
788826 DRM_IOCTL_DEF_DRV(MSM_GEM_MADVISE, msm_ioctl_gem_madvise, DRM_AUTH|DRM_RENDER_ALLOW),
827+ DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_NEW, msm_ioctl_submitqueue_new, DRM_AUTH|DRM_RENDER_ALLOW),
828+ DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_CLOSE, msm_ioctl_submitqueue_close, DRM_AUTH|DRM_RENDER_ALLOW),
789829 };
790830
791831 static const struct vm_operations_struct vm_ops = {
drivers/gpu/drm/msm/msm_drv.h+15−5
@@ -56,11 +56,9 @@ struct msm_gem_address_space; · 55 unmodified lines
5656 struct msm_gem_vma;
5757
5858 struct msm_file_private {
59− /* currently we don't do anything useful with this.. but when
60− * per-context address spaces are supported we'd keep track of
61− * the context's page-tables here.
62− */
63− int dummy;
59+ rwlock_t queuelock;
60+ struct list_head submitqueues;
61+ int queueid;
6462 };
6563
6664 enum msm_mdp_plane_property {
@@ -319,6 +317,18 @@ void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, · 252 unmodified lines
319317 void msm_writel(u32 data, void __iomem *addr);
320318 u32 msm_readl(const void __iomem *addr);
321319
320+struct msm_gpu_submitqueue;
321+int msm_submitqueue_init(struct msm_file_private *ctx);
322+struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx,
323+ u32 id);
324+int msm_submitqueue_create(struct msm_file_private *ctx, u32 prio,
325+ u32 flags, u32 *id);
326+int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id);
327+void msm_submitqueue_close(struct msm_file_private *ctx);
328+
329+void msm_submitqueue_destroy(struct kref *kref);
330+
331+
322332 #define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__)
323333 #define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__)
324334
drivers/gpu/drm/msm/msm_gem.h+1−0
@@ -142,6 +142,7 @@ struct msm_gem_submit { · 141 unmodified lines
142142 struct list_head bo_list;
143143 struct ww_acquire_ctx ticket;
144144 struct dma_fence *fence;
145+ struct msm_gpu_submitqueue *queue;
145146 struct pid *pid; /* submitting process */
146147 bool valid; /* true if no cmdstream patching needed */
147148 unsigned int nr_cmds;
drivers/gpu/drm/msm/msm_gem_submit.c+12−2
@@ -31,7 +31,8 @@ · 30 unmodified lines
3131 #define BO_PINNED 0x2000
3232
3333 static struct msm_gem_submit *submit_create(struct drm_device *dev,
34− struct msm_gpu *gpu, uint32_t nr_bos, uint32_t nr_cmds)
34+ struct msm_gpu *gpu, struct msm_gpu_submitqueue *queue,
35+ uint32_t nr_bos, uint32_t nr_cmds)
3536 {
3637 struct msm_gem_submit *submit;
3738 uint64_t sz = sizeof(*submit) + ((u64)nr_bos * sizeof(submit->bos[0])) +
@@ -49,6 +50,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, · 11 unmodified lines
4950 submit->fence = NULL;
5051 submit->pid = get_pid(task_pid(current));
5152 submit->cmd = (void *)&submit->bos[nr_bos];
53+ submit->queue = queue;
5254
5355 /* initially, until copy_from_user() and bo lookup succeeds: */
5456 submit->nr_bos = 0;
@@ -66,6 +68,8 @@ void msm_gem_submit_free(struct msm_gem_submit *submit) · 11 unmodified lines
6668 dma_fence_put(submit->fence);
6769 list_del(&submit->node);
6870 put_pid(submit->pid);
71+ msm_submitqueue_put(submit->queue);
72+
6973 kfree(submit);
7074 }
7175
@@ -405,6 +409,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 333 unmodified lines
405409 struct msm_gpu *gpu = priv->gpu;
406410 struct dma_fence *in_fence = NULL;
407411 struct sync_file *sync_file = NULL;
412+ struct msm_gpu_submitqueue *queue;
408413 int out_fence_fd = -1;
409414 unsigned i;
410415 int ret;
@@ -421,6 +426,10 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 10 unmodified lines
421426 if (MSM_PIPE_FLAGS(args->flags) & ~MSM_SUBMIT_FLAGS)
422427 return -EINVAL;
423428
429+ queue = msm_submitqueue_get(ctx, args->queueid);
430+ if (!queue)
431+ return -ENOENT;
432+
424433 if (args->flags & MSM_SUBMIT_FENCE_FD_IN) {
425434 in_fence = sync_file_get_fence(args->fence_fd);
426435
@@ -451,7 +460,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 24 unmodified lines
451460 }
452461 priv->struct_mutex_task = current;
453462
454− submit = submit_create(dev, gpu, args->nr_bos, args->nr_cmds);
463+ submit = submit_create(dev, gpu, queue, args->nr_bos, args->nr_cmds);
455464 if (!submit) {
456465 ret = -ENOMEM;
457466 goto out_unlock;
@@ -535,6 +544,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 77 unmodified lines
535544 submit->nr_cmds = i;
536545
537546 submit->fence = msm_fence_alloc(gpu->fctx);
547+
538548 if (IS_ERR(submit->fence)) {
539549 ret = PTR_ERR(submit->fence);
540550 submit->fence = NULL;
drivers/gpu/drm/msm/msm_gpu.h+15−0
@@ -150,6 +150,15 @@ struct msm_gpu_perfcntr { · 149 unmodified lines
150150 const char *name;
151151 };
152152
153+struct msm_gpu_submitqueue {
154+ int id;
155+ u32 flags;
156+ u32 prio;
157+ int faults;
158+ struct list_head node;
159+ struct kref ref;
160+};
161+
153162 static inline void gpu_write(struct msm_gpu *gpu, u32 reg, u32 data)
154163 {
155164 msm_writel(data, gpu->mmio + (reg << 2));
@@ -223,4 +232,10 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev); · 67 unmodified lines
223232 void __init adreno_register(void);
224233 void __exit adreno_unregister(void);
225234
235+static inline void msm_submitqueue_put(struct msm_gpu_submitqueue *queue)
236+{
237+ if (queue)
238+ kref_put(&queue->ref, msm_submitqueue_destroy);
239+}
240+
226241 #endif /* __MSM_GPU_H__ */
drivers/gpu/drm/msm/msm_submitqueue.c+135−0
@@ -0,0 +1,135 @@
1+/* Copyright (c) 2017 The Linux Foundation. All rights reserved.
2+ *
3+ * This program is free software; you can redistribute it and/or modify
4+ * it under the terms of the GNU General Public License version 2 and
5+ * only version 2 as published by the Free Software Foundation.
6+ *
7+ * This program is distributed in the hope that it will be useful,
8+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10+ * GNU General Public License for more details.
11+ *
12+ */
13+
14+#include <linux/kref.h>
15+#include "msm_gpu.h"
16+
17+void msm_submitqueue_destroy(struct kref *kref)
18+{
19+ struct msm_gpu_submitqueue *queue = container_of(kref,
20+ struct msm_gpu_submitqueue, ref);
21+
22+ kfree(queue);
23+}
24+
25+struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx,
26+ u32 id)
27+{
28+ struct msm_gpu_submitqueue *entry;
29+
30+ if (!ctx)
31+ return NULL;
32+
33+ read_lock(&ctx->queuelock);
34+
35+ list_for_each_entry(entry, &ctx->submitqueues, node) {
36+ if (entry->id == id) {
37+ kref_get(&entry->ref);
38+ read_unlock(&ctx->queuelock);
39+
40+ return entry;
41+ }
42+ }
43+
44+ read_unlock(&ctx->queuelock);
45+ return NULL;
46+}
47+
48+void msm_submitqueue_close(struct msm_file_private *ctx)
49+{
50+ struct msm_gpu_submitqueue *entry, *tmp;
51+
52+ if (!ctx)
53+ return;
54+
55+ /*
56+ * No lock needed in close and there won't
57+ * be any more user ioctls coming our way
58+ */
59+ list_for_each_entry_safe(entry, tmp, &ctx->submitqueues, node)
60+ msm_submitqueue_put(entry);
61+}
62+
63+int msm_submitqueue_create(struct msm_file_private *ctx, u32 prio, u32 flags,
64+ u32 *id)
65+{
66+ struct msm_gpu_submitqueue *queue;
67+
68+ if (!ctx)
69+ return -ENODEV;
70+
71+ queue = kzalloc(sizeof(*queue), GFP_KERNEL);
72+
73+ if (!queue)
74+ return -ENOMEM;
75+
76+ kref_init(&queue->ref);
77+ queue->flags = flags;
78+ queue->prio = prio;
79+
80+ write_lock(&ctx->queuelock);
81+
82+ queue->id = ctx->queueid++;
83+
84+ if (id)
85+ *id = queue->id;
86+
87+ list_add_tail(&queue->node, &ctx->submitqueues);
88+
89+ write_unlock(&ctx->queuelock);
90+
91+ return 0;
92+}
93+
94+int msm_submitqueue_init(struct msm_file_private *ctx)
95+{
96+ if (!ctx)
97+ return 0;
98+
99+ INIT_LIST_HEAD(&ctx->submitqueues);
100+
101+ rwlock_init(&ctx->queuelock);
102+
103+ return msm_submitqueue_create(ctx, 2, 0, NULL);
104+}
105+
106+int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id)
107+{
108+ struct msm_gpu_submitqueue *entry;
109+
110+ if (!ctx)
111+ return 0;
112+
113+ /*
114+ * id 0 is the "default" queue and can't be destroyed
115+ * by the user
116+ */
117+ if (!id)
118+ return -ENOENT;
119+
120+ write_lock(&ctx->queuelock);
121+
122+ list_for_each_entry(entry, &ctx->submitqueues, node) {
123+ if (entry->id == id) {
124+ list_del(&entry->node);
125+ write_unlock(&ctx->queuelock);
126+
127+ msm_submitqueue_put(entry);
128+ return 0;
129+ }
130+ }
131+
132+ write_unlock(&ctx->queuelock);
133+ return -ENOENT;
134+}
135+
include/uapi/drm/msm_drm.h+22−0
@@ -218,6 +218,7 @@ struct drm_msm_gem_submit { · 217 unmodified lines
218218 __u64 bos; /* in, ptr to array of submit_bo's */
219219 __u64 cmds; /* in, ptr to array of submit_cmd's */
220220 __s32 fence_fd; /* in/out fence fd (see MSM_SUBMIT_FENCE_FD_IN/OUT) */
221+ __u32 queueid; /* in, submitqueue id */
221222 };
222223
223224 /* The normal way to synchronize with the GPU is just to CPU_PREP on
@@ -254,6 +255,20 @@ struct drm_msm_gem_madvise { · 30 unmodified lines
254255 __u32 retained; /* out, whether backing store still exists */
255256 };
256257
258+/*
259+ * Draw queues allow the user to set specific submission parameter. Command
260+ * submissions specify a specific submitqueue to use. ID 0 is reserved for
261+ * backwards compatibility as a "default" submitqueue
262+ */
263+
264+#define MSM_SUBMITQUEUE_FLAGS (0)
265+
266+struct drm_msm_submitqueue {
267+ __u32 flags; /* in, MSM_SUBMITQUEUE_x */
268+ __u32 prio; /* in, Priority level */
269+ __u32 id; /* out, identifier */
270+};
271+
257272 #define DRM_MSM_GET_PARAM 0x00
258273 /* placeholder:
259274 #define DRM_MSM_SET_PARAM 0x01
@@ -265,6 +280,11 @@ struct drm_msm_gem_madvise { · 5 unmodified lines
265280 #define DRM_MSM_GEM_SUBMIT 0x06
266281 #define DRM_MSM_WAIT_FENCE 0x07
267282 #define DRM_MSM_GEM_MADVISE 0x08
283+/* placeholder:
284+#define DRM_MSM_GEM_SVM_NEW 0x09
285+ */
286+#define DRM_MSM_SUBMITQUEUE_NEW 0x0A
287+#define DRM_MSM_SUBMITQUEUE_CLOSE 0x0B
268288
269289 #define DRM_IOCTL_MSM_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GET_PARAM, struct drm_msm_param)
270290 #define DRM_IOCTL_MSM_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_NEW, struct drm_msm_gem_new)
@@ -274,6 +294,8 @@ struct drm_msm_gem_madvise { · 3 unmodified lines
274294 #define DRM_IOCTL_MSM_GEM_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_SUBMIT, struct drm_msm_gem_submit)
275295 #define DRM_IOCTL_MSM_WAIT_FENCE DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_WAIT_FENCE, struct drm_msm_wait_fence)
276296 #define DRM_IOCTL_MSM_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_MADVISE, struct drm_msm_gem_madvise)
297+#define DRM_IOCTL_MSM_SUBMITQUEUE_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_NEW, struct drm_msm_submitqueue)
298+#define DRM_IOCTL_MSM_SUBMITQUEUE_CLOSE DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_CLOSE, __u32)
277299
278300 #if defined(__cplusplus)
279301 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t