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

Commit 10ea2bdd authored by Veera Sundaram Sankaran's avatar Veera Sundaram Sankaran Committed by Gerrit - the friendly Code Review server
Browse files

drm/msm/sde: move vblank to event thread



Currently vblank is queued as part of display thread and
this would cause vblank to be serviced very late if the
display thread is busy with commit. Move the crtc event
thread to msm level so that, it can be used for crtc
frame/custom events and vblank.

Change-Id: Ifd1f6bc6f80209e7e5a9f945da7a5d075f029a61
Signed-off-by: default avatarVeera Sundaram Sankaran <veeras@codeaurora.org>
parent 2c748e62
Loading
Loading
Loading
Loading
+43 −8
Original line number Diff line number Diff line
@@ -304,7 +304,8 @@ static int vblank_ctrl_queue_work(struct msm_drm_private *priv,
	list_add_tail(&vbl_ev->node, &vbl_ctrl->event_list);
	spin_unlock_irqrestore(&vbl_ctrl->lock, flags);

	kthread_queue_work(&priv->disp_thread[crtc_id].worker, &vbl_ctrl->work);
	kthread_queue_work(&priv->event_thread[crtc_id].worker,
			&vbl_ctrl->work);

	return 0;
}
@@ -330,13 +331,19 @@ static int msm_drm_uninit(struct device *dev)
		kfree(vbl_ev);
	}

	/* clean up display commit worker threads */
	/* clean up display commit/event worker threads */
	for (i = 0; i < priv->num_crtcs; i++) {
		if (priv->disp_thread[i].thread) {
			kthread_flush_worker(&priv->disp_thread[i].worker);
			kthread_stop(priv->disp_thread[i].thread);
			priv->disp_thread[i].thread = NULL;
		}

		if (priv->event_thread[i].thread) {
			kthread_flush_worker(&priv->event_thread[i].worker);
			kthread_stop(priv->event_thread[i].thread);
			priv->event_thread[i].thread = NULL;
		}
	}

	msm_gem_shrinker_cleanup(ddev);
@@ -637,23 +644,51 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
	ddev->mode_config.funcs = &mode_config_funcs;

	for (i = 0; i < priv->num_crtcs; i++) {

		/* initialize display thread */
		priv->disp_thread[i].crtc_id = priv->crtcs[i]->base.id;
		kthread_init_worker(&priv->disp_thread[i].worker);
		priv->disp_thread[i].dev = ddev;
		priv->disp_thread[i].thread =
			kthread_run(kthread_worker_fn,
				&priv->disp_thread[i].worker,
				"crtc_commit:%d",
				priv->disp_thread[i].crtc_id);
				"crtc_commit:%d", priv->disp_thread[i].crtc_id);

		if (IS_ERR(priv->disp_thread[i].thread)) {
			dev_err(dev, "failed to create kthread\n");
			dev_err(dev, "failed to create crtc_commit kthread\n");
			priv->disp_thread[i].thread = NULL;
		}

		/* initialize event thread */
		priv->event_thread[i].crtc_id = priv->crtcs[i]->base.id;
		kthread_init_worker(&priv->event_thread[i].worker);
		priv->event_thread[i].dev = ddev;
		priv->event_thread[i].thread =
			kthread_run(kthread_worker_fn,
				&priv->event_thread[i].worker,
				"crtc_event:%d", priv->event_thread[i].crtc_id);

		if (IS_ERR(priv->event_thread[i].thread)) {
			dev_err(dev, "failed to create crtc_event kthread\n");
			priv->event_thread[i].thread = NULL;
		}

		if ((!priv->disp_thread[i].thread) ||
				!priv->event_thread[i].thread) {
			/* clean up previously created threads if any */
			for (i -= 1; i >= 0; i--) {
				kthread_stop(priv->disp_thread[i].thread);
			for ( ; i >= 0; i--) {
				if (priv->disp_thread[i].thread) {
					kthread_stop(
						priv->disp_thread[i].thread);
					priv->disp_thread[i].thread = NULL;
				}

				if (priv->event_thread[i].thread) {
					kthread_stop(
						priv->event_thread[i].thread);
					priv->event_thread[i].thread = NULL;
				}
			}
			goto fail;
		}
	}
+4 −3
Original line number Diff line number Diff line
@@ -471,8 +471,8 @@ struct msm_drm_event {
	u8 data[];
};

/* Commit thread specific structure */
struct msm_drm_commit {
/* Commit/Event thread specific structure */
struct msm_drm_thread {
	struct drm_device *dev;
	struct task_struct *thread;
	unsigned int crtc_id;
@@ -536,7 +536,8 @@ struct msm_drm_private {
	unsigned int num_crtcs;
	struct drm_crtc *crtcs[MAX_CRTCS];

	struct msm_drm_commit disp_thread[MAX_CRTCS];
	struct msm_drm_thread disp_thread[MAX_CRTCS];
	struct msm_drm_thread event_thread[MAX_CRTCS];

	unsigned int num_encoders;
	struct drm_encoder *encoders[MAX_ENCODERS];
+12 −24
Original line number Diff line number Diff line
@@ -494,12 +494,6 @@ static void _sde_crtc_deinit_events(struct sde_crtc *sde_crtc)
{
	if (!sde_crtc)
		return;

	if (sde_crtc->event_thread) {
		kthread_flush_worker(&sde_crtc->event_worker);
		kthread_stop(sde_crtc->event_thread);
		sde_crtc->event_thread = NULL;
	}
}

static void sde_crtc_destroy(struct drm_crtc *crtc)
@@ -1616,7 +1610,7 @@ static void sde_crtc_frame_event_cb(void *data, u32 event)
	struct msm_drm_private *priv;
	struct sde_crtc_frame_event *fevent;
	unsigned long flags;
	int pipe_id;
	u32 crtc_id;

	if (!crtc || !crtc->dev || !crtc->dev->dev_private) {
		SDE_ERROR("invalid parameters\n");
@@ -1624,7 +1618,7 @@ static void sde_crtc_frame_event_cb(void *data, u32 event)
	}
	sde_crtc = to_sde_crtc(crtc);
	priv = crtc->dev->dev_private;
	pipe_id = drm_crtc_index(crtc);
	crtc_id = drm_crtc_index(crtc);

	SDE_DEBUG("crtc%d\n", crtc->base.id);
	SDE_EVT32_VERBOSE(DRMID(crtc), event);
@@ -1646,7 +1640,7 @@ static void sde_crtc_frame_event_cb(void *data, u32 event)
	fevent->event = event;
	fevent->crtc = crtc;
	fevent->ts = ktime_get();
	kthread_queue_work(&sde_crtc->event_worker, &fevent->work);
	kthread_queue_work(&priv->event_thread[crtc_id].worker, &fevent->work);
}

void sde_crtc_complete_commit(struct drm_crtc *crtc,
@@ -3687,14 +3681,18 @@ int sde_crtc_event_queue(struct drm_crtc *crtc,
{
	unsigned long irq_flags;
	struct sde_crtc *sde_crtc;
	struct msm_drm_private *priv;
	struct sde_crtc_event *event = NULL;
	u32 crtc_id;

	if (!crtc || !func)
	if (!crtc || !crtc->dev || !crtc->dev->dev_private || !func) {
		SDE_ERROR("invalid parameters\n");
		return -EINVAL;
	}
	sde_crtc = to_sde_crtc(crtc);
	priv = crtc->dev->dev_private;
	crtc_id = drm_crtc_index(crtc);

	if (!sde_crtc->event_thread)
		return -EINVAL;
	/*
	 * Obtain an event struct from the private cache. This event
	 * queue may be called from ISR contexts, so use a private
@@ -3718,7 +3716,8 @@ int sde_crtc_event_queue(struct drm_crtc *crtc,

	/* queue new event request */
	kthread_init_work(&event->kt_work, _sde_crtc_event_cb);
	kthread_queue_work(&sde_crtc->event_worker, &event->kt_work);
	kthread_queue_work(&priv->event_thread[crtc_id].worker,
			&event->kt_work);

	return 0;
}
@@ -3739,17 +3738,6 @@ static int _sde_crtc_init_events(struct sde_crtc *sde_crtc)
		list_add_tail(&sde_crtc->event_cache[i].list,
				&sde_crtc->event_free_list);

	kthread_init_worker(&sde_crtc->event_worker);
	sde_crtc->event_thread = kthread_run(kthread_worker_fn,
			&sde_crtc->event_worker, "crtc_event:%d",
			sde_crtc->base.base.id);

	if (IS_ERR_OR_NULL(sde_crtc->event_thread)) {
		SDE_ERROR("failed to create event thread\n");
		rc = PTR_ERR(sde_crtc->event_thread);
		sde_crtc->event_thread = NULL;
	}

	return rc;
}

+0 −2
Original line number Diff line number Diff line
@@ -190,8 +190,6 @@ struct sde_crtc {
	struct completion frame_done_comp;

	/* for handling internal event thread */
	struct task_struct *event_thread;
	struct kthread_worker event_worker;
	struct sde_crtc_event event_cache[SDE_CRTC_MAX_EVENT_COUNT];
	struct list_head event_free_list;
	spinlock_t event_lock;