[PATCH 02/11] drm/i915: Add support for tracking wakerefs w/o power-on guarantee
Imre Deak
imre.deak at intel.com
Wed May 1 08:12:26 UTC 2019
It's useful to track runtime PM refs that don't guarantee a device
power-on state to the rest of the driver. For instance when holding a
ref for disabling runtime PM itself, or holding a reference that will be
put asynchronously, during which normal users without their own
reference shouldn't access the HW. For this we can track all references
with a separate wakeref_track_count and references guaranteeing a
power-on state with the current wakeref_count.
Follow-up patches will make use of the API added here, so add a
__used__ attribute quirk to keep git bisect working.
No functional changes.
Signed-off-by: Imre Deak <imre.deak at intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 1 +
drivers/gpu/drm/i915/intel_runtime_pm.c | 92 ++++++++++++++++++++-----
2 files changed, 74 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 886a30243fe3..cd420791b1aa 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1177,6 +1177,7 @@ struct skl_wm_params {
*/
struct i915_runtime_pm {
atomic_t wakeref_count;
+ atomic_t wakeref_track_count;
bool suspended;
bool irqs_enabled;
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index a0ea38319841..1f4f9e69fa1d 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -100,18 +100,17 @@ static void init_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
struct i915_runtime_pm *rpm = &i915->runtime_pm;
spin_lock_init(&rpm->debug.lock);
+ atomic_set(&rpm->wakeref_track_count, 0);
}
static noinline depot_stack_handle_t
-track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+track_intel_runtime_pm_wakeref_raw(struct drm_i915_private *i915)
{
struct i915_runtime_pm *rpm = &i915->runtime_pm;
depot_stack_handle_t stack, *stacks;
unsigned long flags;
- atomic_inc(&rpm->wakeref_count);
- assert_rpm_wakelock_held(i915);
-
+ atomic_inc(&rpm->wakeref_track_count);
if (!HAS_RUNTIME_PM(i915))
return -1;
@@ -139,6 +138,15 @@ track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
return stack;
}
+static noinline depot_stack_handle_t
+track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+{
+ atomic_inc(&i915->runtime_pm.wakeref_count);
+ assert_rpm_wakelock_held(i915);
+
+ return track_intel_runtime_pm_wakeref_raw(i915);
+}
+
static void cancel_intel_runtime_pm_wakeref(struct drm_i915_private *i915,
depot_stack_handle_t stack)
{
@@ -163,7 +171,7 @@ static void cancel_intel_runtime_pm_wakeref(struct drm_i915_private *i915,
if (WARN(!found,
"Unmatched wakeref (tracking %lu), count %u\n",
- rpm->debug.count, atomic_read(&rpm->wakeref_count))) {
+ rpm->debug.count, atomic_read(&rpm->wakeref_track_count))) {
char *buf;
buf = kmalloc(PAGE_SIZE, GFP_NOWAIT | __GFP_NOWARN);
@@ -235,15 +243,14 @@ __print_intel_runtime_pm_wakeref(struct drm_printer *p,
}
static noinline void
-untrack_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+untrack_intel_runtime_pm_wakeref_raw(struct drm_i915_private *i915)
{
struct i915_runtime_pm *rpm = &i915->runtime_pm;
struct intel_runtime_pm_debug dbg = {};
struct drm_printer p;
unsigned long flags;
- assert_rpm_wakelock_held(i915);
- if (atomic_dec_and_lock_irqsave(&rpm->wakeref_count,
+ if (atomic_dec_and_lock_irqsave(&rpm->wakeref_track_count,
&rpm->debug.lock,
flags)) {
dbg = rpm->debug;
@@ -263,6 +270,15 @@ untrack_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
kfree(dbg.owners);
}
+static noinline void
+untrack_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+{
+ assert_rpm_wakelock_held(i915);
+ atomic_dec(&i915->runtime_pm.wakeref_count);
+
+ untrack_intel_runtime_pm_wakeref_raw(i915);
+}
+
void print_intel_runtime_pm_wakeref(struct drm_i915_private *i915,
struct drm_printer *p)
{
@@ -4347,7 +4363,7 @@ static void intel_power_domains_verify_state(struct drm_i915_private *i915)
*
* Returns: the wakeref cookie to pass to intel_runtime_pm_put()
*/
-intel_wakeref_t intel_runtime_pm_get(struct drm_i915_private *i915)
+static void __intel_runtime_pm_get(struct drm_i915_private *i915)
{
struct pci_dev *pdev = i915->drm.pdev;
struct device *kdev = &pdev->dev;
@@ -4355,10 +4371,23 @@ intel_wakeref_t intel_runtime_pm_get(struct drm_i915_private *i915)
ret = pm_runtime_get_sync(kdev);
WARN_ONCE(ret < 0, "pm_runtime_get_sync() failed: %d\n", ret);
+}
+
+intel_wakeref_t intel_runtime_pm_get(struct drm_i915_private *i915)
+{
+ __intel_runtime_pm_get(i915);
return track_intel_runtime_pm_wakeref(i915);
}
+__attribute__((__used__))
+static intel_wakeref_t intel_runtime_pm_get_raw(struct drm_i915_private *i915)
+{
+ __intel_runtime_pm_get(i915);
+
+ return track_intel_runtime_pm_wakeref_raw(i915);
+}
+
/**
* intel_runtime_pm_get_if_in_use - grab a runtime pm reference if device in use
* @i915: i915 device instance
@@ -4430,15 +4459,25 @@ intel_wakeref_t intel_runtime_pm_get_noresume(struct drm_i915_private *i915)
* intel_runtime_pm_get() and might power down the corresponding
* hardware block right away if this is the last reference.
*/
+static void __intel_runtime_pm_put_unchecked(struct drm_i915_private *i915)
+{
+ struct pci_dev *pdev = i915->drm.pdev;
+ struct device *kdev = &pdev->dev;
+
+ pm_runtime_mark_last_busy(kdev);
+ pm_runtime_put_autosuspend(kdev);
+}
+
+static void intel_runtime_pm_put_unchecked_raw(struct drm_i915_private *i915)
+{
+ untrack_intel_runtime_pm_wakeref_raw(i915);
+ __intel_runtime_pm_put_unchecked(i915);
+}
+
void intel_runtime_pm_put_unchecked(struct drm_i915_private *i915)
{
- struct pci_dev *pdev = i915->drm.pdev;
- struct device *kdev = &pdev->dev;
-
untrack_intel_runtime_pm_wakeref(i915);
-
- pm_runtime_mark_last_busy(kdev);
- pm_runtime_put_autosuspend(kdev);
+ __intel_runtime_pm_put_unchecked(i915);
}
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
@@ -4447,6 +4486,21 @@ void intel_runtime_pm_put(struct drm_i915_private *i915, intel_wakeref_t wref)
cancel_intel_runtime_pm_wakeref(i915, wref);
intel_runtime_pm_put_unchecked(i915);
}
+
+__attribute__((__used__))
+static void intel_runtime_pm_put_raw(struct drm_i915_private *i915,
+ intel_wakeref_t wref)
+{
+ cancel_intel_runtime_pm_wakeref(i915, wref);
+ intel_runtime_pm_put_unchecked_raw(i915);
+}
+#else
+__attribute__((__used__))
+static void intel_runtime_pm_put_raw(struct drm_i915_private *i915,
+ intel_wakeref_t wref)
+{
+ intel_runtime_pm_put_unchecked_raw(i915);
+}
#endif
/**
@@ -4521,12 +4575,12 @@ void intel_runtime_pm_cleanup(struct drm_i915_private *i915)
struct i915_runtime_pm *rpm = &i915->runtime_pm;
int count;
- count = atomic_xchg(&rpm->wakeref_count, 1); /* force printing */
+ count = atomic_xchg(&rpm->wakeref_track_count, 1); /* force printing */
WARN(count,
- "i915->runtime_pm.wakeref_count=%d on cleanup\n",
+ "i915->runtime_pm.wakeref_track_count=%d on cleanup\n",
count);
- untrack_intel_runtime_pm_wakeref(i915);
- atomic_add(count, &rpm->wakeref_count);
+ untrack_intel_runtime_pm_wakeref_raw(i915);
+ atomic_add(count, &rpm->wakeref_track_count);
}
void intel_runtime_pm_init_early(struct drm_i915_private *i915)
--
2.17.1
More information about the Intel-gfx-trybot
mailing list