diff options
author | Jani Nikula <jani.nikula@intel.com> | 2023-05-31 12:01:51 +0300 |
---|---|---|
committer | Jani Nikula <jani.nikula@intel.com> | 2023-05-31 12:01:51 +0300 |
commit | e2a9f0a32464f435dbdb190ff7dbf09745703b60 (patch) | |
tree | bae874fad606918fdae32a99a2b47a76f3a605b3 /drivers/gpu/drm/i915/i915_hwmon.c | |
parent | 3e36c490698660ba4fa7cedfab03f3ed81a07192 (diff) | |
parent | 85d712f033d23bb56a373e29465470c036532d46 (diff) |
Merge drm/drm-next into drm-intel-next
Sync the drm-intel-gt-next changes back to drm-intel-next via drm-next.
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_hwmon.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_hwmon.c | 87 |
1 files changed, 75 insertions, 12 deletions
diff --git a/drivers/gpu/drm/i915/i915_hwmon.c b/drivers/gpu/drm/i915/i915_hwmon.c index e99e8c97ef01..975da8e7f2a9 100644 --- a/drivers/gpu/drm/i915/i915_hwmon.c +++ b/drivers/gpu/drm/i915/i915_hwmon.c @@ -50,6 +50,8 @@ struct hwm_drvdata { struct hwm_energy_info ei; /* Energy info for energy1_input */ char name[12]; int gt_n; + bool reset_in_progress; + wait_queue_head_t waitq; }; struct i915_hwmon { @@ -396,31 +398,56 @@ hwm_power_max_write(struct hwm_drvdata *ddat, long val) { struct i915_hwmon *hwmon = ddat->hwmon; intel_wakeref_t wakeref; + DEFINE_WAIT(wait); + int ret = 0; u32 nval; - /* Disable PL1 limit and verify, because the limit cannot be disabled on all platforms */ - if (val == PL1_DISABLE) { + /* Block waiting for GuC reset to complete when needed */ + for (;;) { mutex_lock(&hwmon->hwmon_lock); - with_intel_runtime_pm(ddat->uncore->rpm, wakeref) { - intel_uncore_rmw(ddat->uncore, hwmon->rg.pkg_rapl_limit, - PKG_PWR_LIM_1_EN, 0); - nval = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit); + + prepare_to_wait(&ddat->waitq, &wait, TASK_INTERRUPTIBLE); + + if (!hwmon->ddat.reset_in_progress) + break; + + if (signal_pending(current)) { + ret = -EINTR; + break; } + mutex_unlock(&hwmon->hwmon_lock); + schedule(); + } + finish_wait(&ddat->waitq, &wait); + if (ret) + goto unlock; + + wakeref = intel_runtime_pm_get(ddat->uncore->rpm); + + /* Disable PL1 limit and verify, because the limit cannot be disabled on all platforms */ + if (val == PL1_DISABLE) { + intel_uncore_rmw(ddat->uncore, hwmon->rg.pkg_rapl_limit, + PKG_PWR_LIM_1_EN, 0); + nval = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit); + if (nval & PKG_PWR_LIM_1_EN) - return -ENODEV; - return 0; + ret = -ENODEV; + goto exit; } /* Computation in 64-bits to avoid overflow. Round to nearest. */ nval = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_power, SF_POWER); nval = PKG_PWR_LIM_1_EN | REG_FIELD_PREP(PKG_PWR_LIM_1, nval); - hwm_locked_with_pm_intel_uncore_rmw(ddat, hwmon->rg.pkg_rapl_limit, - PKG_PWR_LIM_1_EN | PKG_PWR_LIM_1, - nval); - return 0; + intel_uncore_rmw(ddat->uncore, hwmon->rg.pkg_rapl_limit, + PKG_PWR_LIM_1_EN | PKG_PWR_LIM_1, nval); +exit: + intel_runtime_pm_put(ddat->uncore->rpm, wakeref); +unlock: + mutex_unlock(&hwmon->hwmon_lock); + return ret; } static int @@ -470,6 +497,41 @@ hwm_power_write(struct hwm_drvdata *ddat, u32 attr, int chan, long val) } } +void i915_hwmon_power_max_disable(struct drm_i915_private *i915, bool *old) +{ + struct i915_hwmon *hwmon = i915->hwmon; + u32 r; + + if (!hwmon || !i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit)) + return; + + mutex_lock(&hwmon->hwmon_lock); + + hwmon->ddat.reset_in_progress = true; + r = intel_uncore_rmw(hwmon->ddat.uncore, hwmon->rg.pkg_rapl_limit, + PKG_PWR_LIM_1_EN, 0); + *old = !!(r & PKG_PWR_LIM_1_EN); + + mutex_unlock(&hwmon->hwmon_lock); +} + +void i915_hwmon_power_max_restore(struct drm_i915_private *i915, bool old) +{ + struct i915_hwmon *hwmon = i915->hwmon; + + if (!hwmon || !i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit)) + return; + + mutex_lock(&hwmon->hwmon_lock); + + intel_uncore_rmw(hwmon->ddat.uncore, hwmon->rg.pkg_rapl_limit, + PKG_PWR_LIM_1_EN, old ? PKG_PWR_LIM_1_EN : 0); + hwmon->ddat.reset_in_progress = false; + wake_up_all(&hwmon->ddat.waitq); + + mutex_unlock(&hwmon->hwmon_lock); +} + static umode_t hwm_energy_is_visible(const struct hwm_drvdata *ddat, u32 attr) { @@ -742,6 +804,7 @@ void i915_hwmon_register(struct drm_i915_private *i915) ddat->uncore = &i915->uncore; snprintf(ddat->name, sizeof(ddat->name), "i915"); ddat->gt_n = -1; + init_waitqueue_head(&ddat->waitq); for_each_gt(gt, i915, i) { ddat_gt = hwmon->ddat_gt + i; |