freedreno: submit-queue context priority
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>main
parent
62e0767b81
commit
7064b2eae9
|
@ -61,6 +61,7 @@ enum fd_param_id {
|
||||||
FD_CHIP_ID,
|
FD_CHIP_ID,
|
||||||
FD_MAX_FREQ,
|
FD_MAX_FREQ,
|
||||||
FD_TIMESTAMP,
|
FD_TIMESTAMP,
|
||||||
|
FD_NR_RINGS, /* # of rings == # of distinct priority levels */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* bo flags: */
|
/* bo flags: */
|
||||||
|
@ -93,6 +94,7 @@ enum fd_version {
|
||||||
FD_VERSION_MADVISE = 1, /* kernel supports madvise */
|
FD_VERSION_MADVISE = 1, /* kernel supports madvise */
|
||||||
FD_VERSION_UNLIMITED_CMDS = 1, /* submits w/ >4 cmd buffers (growable ringbuffer) */
|
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_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);
|
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_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);
|
void fd_pipe_del(struct fd_pipe *pipe);
|
||||||
int fd_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param,
|
int fd_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param,
|
||||||
uint64_t *value);
|
uint64_t *value);
|
||||||
|
|
|
@ -33,8 +33,12 @@
|
||||||
#include "freedreno_drmif.h"
|
#include "freedreno_drmif.h"
|
||||||
#include "freedreno_priv.h"
|
#include "freedreno_priv.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* priority of zero is highest priority, and higher numeric values are
|
||||||
|
* lower priorities
|
||||||
|
*/
|
||||||
struct fd_pipe *
|
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;
|
struct fd_pipe *pipe;
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
|
@ -44,7 +48,12 @@ fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id)
|
||||||
return NULL;
|
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) {
|
if (!pipe) {
|
||||||
ERROR_MSG("allocation failed");
|
ERROR_MSG("allocation failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -59,6 +68,12 @@ fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id)
|
||||||
return pipe;
|
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)
|
void fd_pipe_del(struct fd_pipe *pipe)
|
||||||
{
|
{
|
||||||
pipe->funcs->destroy(pipe);
|
pipe->funcs->destroy(pipe);
|
||||||
|
|
|
@ -66,7 +66,8 @@ struct fd_device_funcs {
|
||||||
uint32_t flags, uint32_t *handle);
|
uint32_t flags, uint32_t *handle);
|
||||||
struct fd_bo * (*bo_from_handle)(struct fd_device *dev,
|
struct fd_bo * (*bo_from_handle)(struct fd_device *dev,
|
||||||
uint32_t size, uint32_t handle);
|
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);
|
void (*destroy)(struct fd_device *dev);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ static int kgsl_pipe_get_param(struct fd_pipe *pipe,
|
||||||
return 0;
|
return 0;
|
||||||
case FD_MAX_FREQ:
|
case FD_MAX_FREQ:
|
||||||
case FD_TIMESTAMP:
|
case FD_TIMESTAMP:
|
||||||
|
case FD_NR_RINGS:
|
||||||
/* unsupported on kgsl */
|
/* unsupported on kgsl */
|
||||||
return -1;
|
return -1;
|
||||||
default:
|
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,
|
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[] = {
|
static const char *paths[] = {
|
||||||
[FD_PIPE_3D] = "/dev/kgsl-3d0",
|
[FD_PIPE_3D] = "/dev/kgsl-3d0",
|
||||||
|
|
|
@ -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,
|
drm_private void kgsl_pipe_process_pending(struct kgsl_pipe *pipe,
|
||||||
uint32_t timestamp);
|
uint32_t timestamp);
|
||||||
drm_private struct fd_pipe * kgsl_pipe_new(struct fd_device *dev,
|
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,
|
drm_private struct fd_ringbuffer * kgsl_ringbuffer_new(struct fd_pipe *pipe,
|
||||||
uint32_t size);
|
uint32_t size);
|
||||||
|
|
|
@ -71,6 +71,8 @@ static int msm_pipe_get_param(struct fd_pipe *pipe,
|
||||||
return query_param(pipe, MSM_PARAM_MAX_FREQ, value);
|
return query_param(pipe, MSM_PARAM_MAX_FREQ, value);
|
||||||
case FD_TIMESTAMP:
|
case FD_TIMESTAMP:
|
||||||
return query_param(pipe, MSM_PARAM_TIMESTAMP, value);
|
return query_param(pipe, MSM_PARAM_TIMESTAMP, value);
|
||||||
|
case FD_NR_RINGS:
|
||||||
|
return query_param(pipe, MSM_PARAM_NR_RINGS, value);
|
||||||
default:
|
default:
|
||||||
ERROR_MSG("invalid param id: %d", param);
|
ERROR_MSG("invalid param id: %d", param);
|
||||||
return -1;
|
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 fd_device *dev = pipe->dev;
|
||||||
struct drm_msm_wait_fence req = {
|
struct drm_msm_wait_fence req = {
|
||||||
.fence = timestamp,
|
.fence = timestamp,
|
||||||
|
.queueid = to_msm_pipe(pipe)->queue_id,
|
||||||
};
|
};
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -97,9 +100,42 @@ static int msm_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp,
|
||||||
return 0;
|
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)
|
static void msm_pipe_destroy(struct fd_pipe *pipe)
|
||||||
{
|
{
|
||||||
struct msm_pipe *msm_pipe = to_msm_pipe(pipe);
|
struct msm_pipe *msm_pipe = to_msm_pipe(pipe);
|
||||||
|
close_submitqueue(pipe->dev, msm_pipe->queue_id);
|
||||||
free(msm_pipe);
|
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,
|
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[] = {
|
static const uint32_t pipe_id[] = {
|
||||||
[FD_PIPE_3D] = MSM_PIPE_3D0,
|
[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(" Chip-id: 0x%08x", msm_pipe->chip_id);
|
||||||
INFO_MSG(" GMEM size: 0x%08x", msm_pipe->gmem);
|
INFO_MSG(" GMEM size: 0x%08x", msm_pipe->gmem);
|
||||||
|
|
||||||
|
if (open_submitqueue(dev, prio, &msm_pipe->queue_id))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
return pipe;
|
return pipe;
|
||||||
fail:
|
fail:
|
||||||
if (pipe)
|
if (pipe)
|
||||||
|
|
|
@ -56,6 +56,7 @@ struct msm_pipe {
|
||||||
uint32_t gpu_id;
|
uint32_t gpu_id;
|
||||||
uint32_t gmem;
|
uint32_t gmem;
|
||||||
uint32_t chip_id;
|
uint32_t chip_id;
|
||||||
|
uint32_t queue_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct msm_pipe * to_msm_pipe(struct fd_pipe *x)
|
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,
|
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,
|
drm_private struct fd_ringbuffer * msm_ringbuffer_new(struct fd_pipe *pipe,
|
||||||
uint32_t size);
|
uint32_t size);
|
||||||
|
|
|
@ -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 msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
|
||||||
struct drm_msm_gem_submit req = {
|
struct drm_msm_gem_submit req = {
|
||||||
.flags = to_msm_pipe(ring->pipe)->pipe,
|
.flags = to_msm_pipe(ring->pipe)->pipe,
|
||||||
|
.queueid = to_msm_pipe(ring->pipe)->queue_id,
|
||||||
};
|
};
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
Loading…
Reference in New Issue