All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
To: intel-gfx@lists.freedesktop.org
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Subject: [PATCH 1/3] drm: Add vblank prepare and unprepare hooks.
Date: Wed,  8 Jun 2016 18:46:02 -0700	[thread overview]
Message-ID: <1465436764-29950-2-git-send-email-dhinakaran.pandiyan@intel.com> (raw)
In-Reply-To: <1465436764-29950-1-git-send-email-dhinakaran.pandiyan@intel.com>

From: Rodrigo Vivi <rodrigo.vivi@intel.com>

This will allow drivers to control specific power saving
feature and power domains when dealing with vblanks.

Vblanks code are protected by spin_locks where we can't
have anything that can sleep. While power saving features
and power domain code have mutexes to control the states.

Mutex can sleep so they cannot be used inside spin lock areas.
So the easiest way to deal with them currently is to add these
prepare hook for pre enabling vblanks
and unprepare one for post disabling them.

Let's introduce this optional prepare and unprepare
hooks so drivers can deal with cases like this and any other
case that should require sleeping codes interacting with vblanks.

Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
---
 drivers/gpu/drm/drm_irq.c | 28 +++++++++++++++++++++++++++-
 include/drm/drmP.h        | 30 ++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index d3124b6..c833a5d 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -411,6 +411,8 @@ void drm_vblank_cleanup(struct drm_device *dev)
 			drm_core_check_feature(dev, DRIVER_MODESET));
 
 		del_timer_sync(&vblank->disable_timer);
+
+		flush_work(&vblank->unprepare.work);
 	}
 
 	kfree(dev->vblank);
@@ -419,6 +421,20 @@ void drm_vblank_cleanup(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_vblank_cleanup);
 
+static void drm_vblank_unprepare_work_fn(struct work_struct *work)
+{
+	struct drm_vblank_crtc *vblank;
+	struct drm_device *dev;
+
+	vblank = container_of(work, typeof(*vblank), unprepare.work);
+	dev = vblank->dev;
+
+	do {
+		if (dev->driver->unprepare_vblank)
+			dev->driver->unprepare_vblank(dev, vblank->pipe);
+	} while (!atomic_dec_and_test(&vblank->unprepare.counter));
+}
+
 /**
  * drm_vblank_init - initialize vblank support
  * @dev: DRM device
@@ -451,6 +467,8 @@ int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs)
 		init_waitqueue_head(&vblank->queue);
 		setup_timer(&vblank->disable_timer, vblank_disable_fn,
 			    (unsigned long)vblank);
+		INIT_WORK(&vblank->unprepare.work,
+			  drm_vblank_unprepare_work_fn);
 	}
 
 	DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n");
@@ -1241,6 +1259,9 @@ int drm_vblank_get(struct drm_device *dev, unsigned int pipe)
 	if (WARN_ON(pipe >= dev->num_crtcs))
 		return -EINVAL;
 
+	if (dev->driver->prepare_vblank)
+		dev->driver->prepare_vblank(dev, pipe);
+
 	spin_lock_irqsave(&dev->vbl_lock, irqflags);
 	/* Going from 0->1 means we have to enable interrupts again */
 	if (atomic_add_return(1, &vblank->refcount) == 1) {
@@ -1253,6 +1274,9 @@ int drm_vblank_get(struct drm_device *dev, unsigned int pipe)
 	}
 	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 
+	if (ret != 0 && dev->driver->unprepare_vblank)
+		dev->driver->unprepare_vblank(dev, pipe);
+
 	return ret;
 }
 EXPORT_SYMBOL(drm_vblank_get);
@@ -1305,6 +1329,9 @@ void drm_vblank_put(struct drm_device *dev, unsigned int pipe)
 			mod_timer(&vblank->disable_timer,
 				  jiffies + ((drm_vblank_offdelay * HZ)/1000));
 	}
+
+	atomic_inc(&vblank->unprepare.counter);
+	schedule_work(&vblank->unprepare.work);
 }
 EXPORT_SYMBOL(drm_vblank_put);
 
@@ -1740,7 +1767,6 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
 	}
 
 	spin_unlock_irqrestore(&dev->event_lock, flags);
-
 	return 0;
 
 err_unlock:
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index ed89038..544c65f 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -447,6 +447,30 @@ struct drm_driver {
 	u32 (*get_vblank_counter) (struct drm_device *dev, unsigned int pipe);
 
 	/**
+	 * prepare_vblank - Optional prepare vblank hook.
+	 * @dev: DRM device
+	 * @pipe: counter to fetch
+	 *
+	 * Drivers that need to handle any kind of mutex or any other sleeping
+	 * code in combination with vblanks need to implement this hook
+	 * that will be called before drm_vblank_get spin_lock gets.
+	 */
+	void (*prepare_vblank) (struct drm_device *dev, unsigned int pipe);
+
+	/**
+	 * unprepare_vblank - Optional unprepare vblank hook.
+	 * @dev: DRM device
+	 * @pipe: counter to fetch
+	 *
+	 * Drivers that need to handle any kind of mutex or any other sleeping
+	 * code in combination with vblanks need to implement this hook
+	 * that will be called in a work queue to be executed after spin lock
+	 * areas of drm_vblank_put.
+	 */
+	void (*unprepare_vblank) (struct drm_device *dev, unsigned int pipe);
+
+
+	/**
 	 * enable_vblank - enable vblank interrupt events
 	 * @dev: DRM device
 	 * @pipe: which irq to enable
@@ -720,6 +744,11 @@ struct drm_pending_vblank_event {
 	struct drm_event_vblank event;
 };
 
+struct drm_vblank_unprepare {
+	struct work_struct work;	/* Post disable worker */
+	atomic_t counter;		/* Number of vblanks handled */
+};
+
 struct drm_vblank_crtc {
 	struct drm_device *dev;		/* pointer to the drm_device */
 	wait_queue_head_t queue;	/**< VBLANK wait queue */
@@ -740,6 +769,7 @@ struct drm_vblank_crtc {
 	int linedur_ns;			/* line duration in ns */
 	bool enabled;			/* so we don't call enable more than
 					   once per disable */
+	struct drm_vblank_unprepare unprepare;  /* Unprepare work helper */
 };
 
 /**
-- 
2.5.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2016-06-09  1:33 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-09  1:46 [PATCH 0/3] CHV vblank failures when PSR is active Dhinakaran Pandiyan
2016-06-09  1:46 ` Dhinakaran Pandiyan [this message]
2016-06-10 21:21   ` REBASED: [PATCH 1/3] drm: Add vblank prepare and unprepare hooks Dhinakaran Pandiyan
2016-06-09  1:46 ` [PATCH 2/3] drm/i915: Move drm_crtc_vblank_get out of disabled pre-emption area Dhinakaran Pandiyan
2016-06-09  1:46 ` [PATCH 3/3] drm/i915/psr: Do not activate PSR when vblank interrupts are enabled Dhinakaran Pandiyan
2016-06-09  3:06   ` kbuild test robot
2016-06-14  0:09   ` Vivi, Rodrigo
2016-06-15  1:02     ` Pandiyan, Dhinakaran
2016-06-15 21:44       ` Vivi, Rodrigo
2016-06-24 18:39         ` Pandiyan, Dhinakaran
2016-06-09  5:00 ` ✗ Ro.CI.BAT: failure for CHV vblank failures when PSR is active Patchwork
2016-06-09  8:31 ` [PATCH 0/3] " Jani Nikula
2016-06-09  8:35   ` Ville Syrjälä
2016-06-11  6:32 ` ✗ Ro.CI.BAT: warning for CHV vblank failures when PSR is active (rev2) Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1465436764-29950-2-git-send-email-dhinakaran.pandiyan@intel.com \
    --to=dhinakaran.pandiyan@intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=rodrigo.vivi@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.