freedreno: submit-queue context priority
authorRob Clark <robclark@freedesktop.org>
Wed, 23 Aug 2017 21:08:39 +0000 (17:08 -0400)
committerRob Clark <robclark@freedesktop.org>
Sat, 4 Nov 2017 21:23:20 +0000 (17:23 -0400)
With a new-enough kernel to support prioritized submit-queues, we can
expose priority level support to mesa.  Open a submit queue associated
with the fd_pipe and pass it's id back to SUBMIT ioctl.

Signed-off-by: Rob Clark <robclark@freedesktop.org>
freedreno/freedreno_drmif.h
freedreno/freedreno_pipe.c
freedreno/freedreno_priv.h
freedreno/kgsl/kgsl_pipe.c
freedreno/kgsl/kgsl_priv.h
freedreno/msm/msm_pipe.c
freedreno/msm/msm_priv.h
freedreno/msm/msm_ringbuffer.c

index 7a8073f..c3b0d02 100644 (file)
@@ -61,6 +61,7 @@ enum fd_param_id {
        FD_CHIP_ID,
        FD_MAX_FREQ,
        FD_TIMESTAMP,
+       FD_NR_RINGS,      /* # of rings == # of distinct priority levels */
 };
 
 /* bo flags: */
@@ -93,6 +94,7 @@ enum fd_version {
        FD_VERSION_MADVISE = 1,            /* kernel supports madvise */
        FD_VERSION_UNLIMITED_CMDS = 1,     /* submits w/ >4 cmd buffers (growable ringbuffer) */
        FD_VERSION_FENCE_FD = 2,           /* submit command supports in/out fences */
+       FD_VERSION_SUBMIT_QUEUES = 3,      /* submit queues and multiple priority levels */
 };
 enum fd_version fd_device_version(struct fd_device *dev);
 
@@ -100,6 +102,7 @@ enum fd_version fd_device_version(struct fd_device *dev);
  */
 
 struct fd_pipe * fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id);
+struct fd_pipe * fd_pipe_new2(struct fd_device *dev, enum fd_pipe_id id, uint32_t prio);
 void fd_pipe_del(struct fd_pipe *pipe);
 int fd_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param,
                uint64_t *value);
index e69cb28..1540474 100644 (file)
 #include "freedreno_drmif.h"
 #include "freedreno_priv.h"
 
+/**
+ * priority of zero is highest priority, and higher numeric values are
+ * lower priorities
+ */
 struct fd_pipe *
-fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id)
+fd_pipe_new2(struct fd_device *dev, enum fd_pipe_id id, uint32_t prio)
 {
        struct fd_pipe *pipe;
        uint64_t val;
@@ -44,7 +48,12 @@ fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id)
                return NULL;
        }
 
-       pipe = dev->funcs->pipe_new(dev, id);
+       if ((prio != 1) && (fd_device_version(dev) < FD_VERSION_SUBMIT_QUEUES)) {
+               ERROR_MSG("invalid priority!");
+               return NULL;
+       }
+
+       pipe = dev->funcs->pipe_new(dev, id, prio);
        if (!pipe) {
                ERROR_MSG("allocation failed");
                return NULL;
@@ -59,6 +68,12 @@ fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id)
        return pipe;
 }
 
+struct fd_pipe *
+fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id)
+{
+       return fd_pipe_new2(dev, id, 1);
+}
+
 void fd_pipe_del(struct fd_pipe *pipe)
 {
        pipe->funcs->destroy(pipe);
index 8dd3ee6..2730747 100644 (file)
@@ -66,7 +66,8 @@ struct fd_device_funcs {
                        uint32_t flags, uint32_t *handle);
        struct fd_bo * (*bo_from_handle)(struct fd_device *dev,
                        uint32_t size, uint32_t handle);
-       struct fd_pipe * (*pipe_new)(struct fd_device *dev, enum fd_pipe_id id);
+       struct fd_pipe * (*pipe_new)(struct fd_device *dev, enum fd_pipe_id id,
+                       unsigned prio);
        void (*destroy)(struct fd_device *dev);
 };
 
index 8a39eb4..80bd131 100644 (file)
@@ -52,6 +52,7 @@ static int kgsl_pipe_get_param(struct fd_pipe *pipe,
                return 0;
        case FD_MAX_FREQ:
        case FD_TIMESTAMP:
+       case FD_NR_RINGS:
                /* unsupported on kgsl */
                return -1;
        default:
@@ -210,7 +211,7 @@ static int getprop(int fd, enum kgsl_property_type type,
 
 
 drm_private struct fd_pipe * kgsl_pipe_new(struct fd_device *dev,
-               enum fd_pipe_id id)
+               enum fd_pipe_id id, uint32_t prio)
 {
        static const char *paths[] = {
                        [FD_PIPE_3D] = "/dev/kgsl-3d0",
index 6ab6496..41b1392 100644 (file)
@@ -103,7 +103,7 @@ drm_private void kgsl_pipe_post_submit(struct kgsl_pipe *pipe,
 drm_private void kgsl_pipe_process_pending(struct kgsl_pipe *pipe,
                uint32_t timestamp);
 drm_private struct fd_pipe * kgsl_pipe_new(struct fd_device *dev,
-               enum fd_pipe_id id);
+               enum fd_pipe_id id, uint32_t prio);
 
 drm_private struct fd_ringbuffer * kgsl_ringbuffer_new(struct fd_pipe *pipe,
                uint32_t size);
index f872e24..7395e57 100644 (file)
@@ -71,6 +71,8 @@ static int msm_pipe_get_param(struct fd_pipe *pipe,
                return query_param(pipe, MSM_PARAM_MAX_FREQ, value);
        case FD_TIMESTAMP:
                return query_param(pipe, MSM_PARAM_TIMESTAMP, value);
+       case FD_NR_RINGS:
+               return query_param(pipe, MSM_PARAM_NR_RINGS, value);
        default:
                ERROR_MSG("invalid param id: %d", param);
                return -1;
@@ -83,6 +85,7 @@ static int msm_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp,
        struct fd_device *dev = pipe->dev;
        struct drm_msm_wait_fence req = {
                        .fence = timestamp,
+                       .queueid = to_msm_pipe(pipe)->queue_id,
        };
        int ret;
 
@@ -97,9 +100,42 @@ static int msm_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp,
        return 0;
 }
 
+static int open_submitqueue(struct fd_device *dev, uint32_t prio,
+               uint32_t *queue_id)
+{
+       struct drm_msm_submitqueue req = {
+               .flags = 0,
+               .prio = prio,
+       };
+       int ret;
+
+       if (fd_device_version(dev) < FD_VERSION_SUBMIT_QUEUES) {
+               *queue_id = 0;
+               return 0;
+       }
+
+       ret = drmCommandWriteRead(dev->fd, DRM_MSM_SUBMITQUEUE_NEW, &req, sizeof(req));
+       if (ret) {
+               ERROR_MSG("could not create submitqueue! %d (%s)", ret, strerror(errno));
+               return ret;
+       }
+
+       *queue_id = req.id;
+       return 0;
+}
+
+static void close_submitqueue(struct fd_device *dev, uint32_t queue_id)
+{
+       if (fd_device_version(dev) < FD_VERSION_SUBMIT_QUEUES)
+               return;
+
+       drmCommandWrite(dev->fd, DRM_MSM_SUBMITQUEUE_CLOSE, &queue_id, sizeof(queue_id));
+}
+
 static void msm_pipe_destroy(struct fd_pipe *pipe)
 {
        struct msm_pipe *msm_pipe = to_msm_pipe(pipe);
+       close_submitqueue(pipe->dev, msm_pipe->queue_id);
        free(msm_pipe);
 }
 
@@ -122,7 +158,7 @@ static uint64_t get_param(struct fd_pipe *pipe, uint32_t param)
 }
 
 drm_private struct fd_pipe * msm_pipe_new(struct fd_device *dev,
-               enum fd_pipe_id id)
+               enum fd_pipe_id id, uint32_t prio)
 {
        static const uint32_t pipe_id[] = {
                        [FD_PIPE_3D] = MSM_PIPE_3D0,
@@ -157,6 +193,9 @@ drm_private struct fd_pipe * msm_pipe_new(struct fd_device *dev,
        INFO_MSG(" Chip-id:         0x%08x", msm_pipe->chip_id);
        INFO_MSG(" GMEM size:       0x%08x", msm_pipe->gmem);
 
+       if (open_submitqueue(dev, prio, &msm_pipe->queue_id))
+               goto fail;
+
        return pipe;
 fail:
        if (pipe)
index 6d670aa..88ac3aa 100644 (file)
@@ -56,6 +56,7 @@ struct msm_pipe {
        uint32_t gpu_id;
        uint32_t gmem;
        uint32_t chip_id;
+       uint32_t queue_id;
 };
 
 static inline struct msm_pipe * to_msm_pipe(struct fd_pipe *x)
@@ -64,7 +65,7 @@ static inline struct msm_pipe * to_msm_pipe(struct fd_pipe *x)
 }
 
 drm_private struct fd_pipe * msm_pipe_new(struct fd_device *dev,
-               enum fd_pipe_id id);
+               enum fd_pipe_id id, uint32_t prio);
 
 drm_private struct fd_ringbuffer * msm_ringbuffer_new(struct fd_pipe *pipe,
                uint32_t size);
index 5b28fea..c75bb16 100644 (file)
@@ -401,6 +401,7 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start
        struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
        struct drm_msm_gem_submit req = {
                        .flags = to_msm_pipe(ring->pipe)->pipe,
+                       .queueid = to_msm_pipe(ring->pipe)->queue_id,
        };
        uint32_t i;
        int ret;