Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7d46546d authored by Jordan Crouse's avatar Jordan Crouse
Browse files

drm/msm: Add per-instance submit queues



Currently the priority and other 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
permisson 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 middle 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.

In addition to the basic infrastructure, allow the user to specify
the queue priority - this will be used in lieu of the legacy
flags to set priority during the submission. Only the master DRM
instance can set the highest priority, but all the others are open
to all processes.

Change-Id: Ic0dedbad02fa27c0ba20c1157a05ddb143e46357
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent 7851820e
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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
+44 −4
Original line number Diff line number Diff line
@@ -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,13 +634,19 @@ 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) {
		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 = {
+13 −0
Original line number Diff line number Diff line
@@ -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);
+5 −0
Original line number Diff line number Diff line
@@ -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 {
+12 −5
Original line number Diff line number Diff line
@@ -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;
@@ -514,9 +523,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);

Loading