dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/16] Enable GuC based power management features
@ 2021-07-10  1:20 Vinay Belgaumkar
  2021-07-10  1:20 ` [PATCH 02/16] drm/i915/guc/slpc: Initial definitions for slpc Vinay Belgaumkar
                   ` (14 more replies)
  0 siblings, 15 replies; 49+ messages in thread
From: Vinay Belgaumkar @ 2021-07-10  1:20 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Vinay Belgaumkar

This series enables Single Loop Power Control (SLPC) feature in GuC.
GuC implements various power management algorithms as part of it's
operation. These need to be specifically enabled by KMD. They replace
the legacy host based management of these features.

With this series, we will enable two PM features - GTPerf and GuCRC. These
are the Turbo and RC6 equivalents of the host based version. GuC provides
various interfaces via host-to-guc messaging, which allows KMD to enable
these features after GuC is loaded and GuC submission is enabled. We will
specifically disable the IA/GT Balancer and Duty Cycle control features in
SLPC.

To enable GTPerf, KMD sends a specific h2g message after setting up
some shared data structures. As part of this, we will gate host RPS as 
well. GuC takes over the duties of requesting frequencies by monitoring
GPU busyness. We can influence what GuC requests by modifying the min 
and max frequencies setup by SLPC through the sysfs interfaces that have
been exposed by legacy Turbo. SLPC typically requests efficient frequency
instead of minimum frequency to optimize performance. It also does not
necessarily stick to platform max, and can request frequencies that are
much higher since pcode will ultimately grant the appropriate values.
However, we will force it to adhere to platform min and max values so as
to maintain legacy behavior. SLPC does not have the concept of waitboost,
so the boost_freq sysfs will show a '0' value for now. There is a patch
forthcoming to ensure the interface is not exposed when slpc is enabled.

GuCRC is enabled similarly through a h2g message. We still need to enable
RC6 feature bit (GEN6_RC_CTL_RC6_ENABLE) before we send this out.
Render/Media power gating still needs to be enabled by host as before.
GuC will take care of setting up the hysterisis values for RC6, host
does not need to set this up anymore.

Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>

Matthew Brost (1):
  drm/i915/guc: Squashed patch - DO NOT REVIEW

Vinay Belgaumkar (15):
  drm/i915/guc/slpc: Initial definitions for slpc
  drm/i915/guc/slpc: Gate Host RPS when slpc is enabled
  drm/i915/guc/slpc: Lay out slpc init/enable/disable/fini
  drm/i915/guc/slpc: Adding slpc communication interfaces
  drm/i915/guc/slpc: Allocate, initialize and release slpc
  drm/i915/guc/slpc: Enable slpc and add related H2G events
  drm/i915/guc/slpc: Add methods to set min/max frequency
  drm/i915/guc/slpc: Add get max/min freq hooks
  drm/i915/guc/slpc: Add debugfs for slpc info
  drm/i915/guc/slpc: Enable ARAT timer interrupt
  drm/i915/guc/slpc: Cache platform frequency limits for slpc
  drm/i915/guc/slpc: Update slpc to use platform min/max
  drm/i915/guc/slpc: Sysfs hooks for slpc
  drm/i915/guc/slpc: slpc selftest
  drm/i915/guc/rc: Setup and enable GUCRC feature

 drivers/gpu/drm/i915/Makefile                 |    3 +
 drivers/gpu/drm/i915/gem/i915_gem_context.c   |   21 +-
 drivers/gpu/drm/i915/gem/i915_gem_context.h   |    1 +
 drivers/gpu/drm/i915/gem/i915_gem_mman.c      |    3 +-
 drivers/gpu/drm/i915/gt/gen8_engine_cs.c      |    6 +-
 drivers/gpu/drm/i915/gt/intel_breadcrumbs.c   |   41 +-
 drivers/gpu/drm/i915/gt/intel_breadcrumbs.h   |   14 +-
 .../gpu/drm/i915/gt/intel_breadcrumbs_types.h |    7 +
 drivers/gpu/drm/i915/gt/intel_context.c       |   50 +-
 drivers/gpu/drm/i915/gt/intel_context.h       |   50 +-
 drivers/gpu/drm/i915/gt/intel_context_types.h |   54 +
 drivers/gpu/drm/i915/gt/intel_engine.h        |   54 +-
 drivers/gpu/drm/i915/gt/intel_engine_cs.c     |  182 +-
 .../gpu/drm/i915/gt/intel_engine_heartbeat.c  |   71 +-
 .../gpu/drm/i915/gt/intel_engine_heartbeat.h  |    4 +
 drivers/gpu/drm/i915/gt/intel_engine_types.h  |   12 +-
 .../drm/i915/gt/intel_execlists_submission.c  |   95 +-
 .../drm/i915/gt/intel_execlists_submission.h  |    4 -
 drivers/gpu/drm/i915/gt/intel_gt.c            |   23 +-
 drivers/gpu/drm/i915/gt/intel_gt.h            |    2 +
 drivers/gpu/drm/i915/gt/intel_gt_pm.c         |    6 +-
 drivers/gpu/drm/i915/gt/intel_gt_requests.c   |   23 +-
 drivers/gpu/drm/i915/gt/intel_gt_requests.h   |    9 +-
 drivers/gpu/drm/i915/gt/intel_lrc_reg.h       |    1 -
 drivers/gpu/drm/i915/gt/intel_rc6.c           |   22 +-
 drivers/gpu/drm/i915/gt/intel_reset.c         |   50 +-
 .../gpu/drm/i915/gt/intel_ring_submission.c   |   48 +
 drivers/gpu/drm/i915/gt/intel_rps.c           |  160 ++
 drivers/gpu/drm/i915/gt/intel_rps.h           |    5 +
 drivers/gpu/drm/i915/gt/intel_workarounds.c   |   46 +-
 .../gpu/drm/i915/gt/intel_workarounds_types.h |    1 +
 drivers/gpu/drm/i915/gt/mock_engine.c         |   41 +-
 drivers/gpu/drm/i915/gt/selftest_context.c    |   10 +
 .../drm/i915/gt/selftest_engine_heartbeat.c   |   22 +
 .../drm/i915/gt/selftest_engine_heartbeat.h   |    2 +
 drivers/gpu/drm/i915/gt/selftest_execlists.c  |   12 +-
 drivers/gpu/drm/i915/gt/selftest_hangcheck.c  |  314 +-
 drivers/gpu/drm/i915/gt/selftest_mocs.c       |   50 +-
 drivers/gpu/drm/i915/gt/selftest_slpc.c       |  333 +++
 drivers/gpu/drm/i915/gt/selftest_slpc.h       |   12 +
 .../gpu/drm/i915/gt/selftest_workarounds.c    |  132 +-
 .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h  |   21 +
 .../gt/uc/abi/guc_communication_ctb_abi.h     |    3 +-
 drivers/gpu/drm/i915/gt/uc/intel_guc.c        |   99 +-
 drivers/gpu/drm/i915/gt/uc/intel_guc.h        |  114 +-
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c    |  460 ++-
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h    |    3 +
 drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c     |  368 ++-
 drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h     |   28 +-
 .../gpu/drm/i915/gt/uc/intel_guc_debugfs.c    |   41 +-
 drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h   |   90 +-
 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c     |   79 +
 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h     |   32 +
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c   |  606 ++++
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h   |   47 +
 .../gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h  |  255 ++
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 2528 +++++++++++++++--
 .../gpu/drm/i915/gt/uc/intel_guc_submission.h |   33 +-
 drivers/gpu/drm/i915/gt/uc/intel_uc.c         |  126 +-
 drivers/gpu/drm/i915/gt/uc/intel_uc.h         |   14 +
 drivers/gpu/drm/i915/i915_debugfs.c           |    2 +
 drivers/gpu/drm/i915/i915_debugfs_params.c    |   31 +
 drivers/gpu/drm/i915/i915_gem_evict.c         |    1 +
 drivers/gpu/drm/i915/i915_gpu_error.c         |   25 +-
 drivers/gpu/drm/i915/i915_pmu.c               |    2 +-
 drivers/gpu/drm/i915/i915_reg.h               |    4 +
 drivers/gpu/drm/i915/i915_request.c           |  168 +-
 drivers/gpu/drm/i915/i915_request.h           |   21 +
 drivers/gpu/drm/i915/i915_scheduler.c         |    9 +-
 drivers/gpu/drm/i915/i915_scheduler.h         |   10 +-
 drivers/gpu/drm/i915/i915_scheduler_types.h   |   10 +
 drivers/gpu/drm/i915/i915_sysfs.c             |   71 +-
 drivers/gpu/drm/i915/i915_trace.h             |  207 +-
 .../drm/i915/selftests/i915_live_selftests.h  |    1 +
 drivers/gpu/drm/i915/selftests/i915_request.c |    4 +-
 .../gpu/drm/i915/selftests/igt_flush_test.c   |    2 +-
 .../gpu/drm/i915/selftests/igt_live_test.c    |    2 +-
 .../i915/selftests/intel_scheduler_helpers.c  |   89 +
 .../i915/selftests/intel_scheduler_helpers.h  |   35 +
 .../gpu/drm/i915/selftests/mock_gem_device.c  |    3 +-
 80 files changed, 6705 insertions(+), 935 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gt/selftest_slpc.c
 create mode 100644 drivers/gpu/drm/i915/gt/selftest_slpc.h
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h
 create mode 100644 drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c
 create mode 100644 drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.h

-- 
2.25.0


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH 02/16] drm/i915/guc/slpc: Initial definitions for slpc
  2021-07-10  1:20 [PATCH 00/16] Enable GuC based power management features Vinay Belgaumkar
@ 2021-07-10  1:20 ` Vinay Belgaumkar
  2021-07-10 14:27   ` Michal Wajdeczko
  2021-07-10  1:20 ` [PATCH 03/16] drm/i915/guc/slpc: Gate Host RPS when slpc is enabled Vinay Belgaumkar
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 49+ messages in thread
From: Vinay Belgaumkar @ 2021-07-10  1:20 UTC (permalink / raw)
  To: intel-gfx, dri-devel
  Cc: Vinay Belgaumkar, Daniele Ceraolo Spurio, Sundaresan Sujaritha

Add macros to check for slpc support. This feature is currently supported
for gen12+ and enabled whenever guc submission is enabled/selected.

Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
---
 drivers/gpu/drm/i915/gt/uc/intel_guc.c        |  1 +
 drivers/gpu/drm/i915/gt/uc/intel_guc.h        |  2 ++
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 21 +++++++++++++++++++
 .../gpu/drm/i915/gt/uc/intel_guc_submission.h | 16 ++++++++++++++
 drivers/gpu/drm/i915/gt/uc/intel_uc.c         |  6 ++++--
 drivers/gpu/drm/i915/gt/uc/intel_uc.h         |  1 +
 6 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index 979128e28372..b9a809f2d221 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -157,6 +157,7 @@ void intel_guc_init_early(struct intel_guc *guc)
 	intel_guc_ct_init_early(&guc->ct);
 	intel_guc_log_init_early(&guc->log);
 	intel_guc_submission_init_early(guc);
+	intel_guc_slpc_init_early(guc);
 
 	mutex_init(&guc->send_mutex);
 	spin_lock_init(&guc->irq_lock);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
index 5d94cf482516..e5a456918b88 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
@@ -57,6 +57,8 @@ struct intel_guc {
 
 	bool submission_supported;
 	bool submission_selected;
+	bool slpc_supported;
+	bool slpc_selected;
 
 	struct i915_vma *ads_vma;
 	struct __guc_ads_blob *ads_blob;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
index 9c102bf0c8e3..e2644a05f298 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
@@ -2351,6 +2351,27 @@ void intel_guc_submission_init_early(struct intel_guc *guc)
 	guc->submission_selected = __guc_submission_selected(guc);
 }
 
+static bool __guc_slpc_supported(struct intel_guc *guc)
+{
+	/* GuC slpc is unavailable for pre-Gen12 */
+	return guc->submission_supported &&
+		GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12;
+}
+
+static bool __guc_slpc_selected(struct intel_guc *guc)
+{
+	if (!intel_guc_slpc_is_supported(guc))
+		return false;
+
+	return guc->submission_selected;
+}
+
+void intel_guc_slpc_init_early(struct intel_guc *guc)
+{
+	guc->slpc_supported = __guc_slpc_supported(guc);
+	guc->slpc_selected = __guc_slpc_selected(guc);
+}
+
 static inline struct intel_context *
 g2h_context_lookup(struct intel_guc *guc, u32 desc_idx)
 {
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
index be767eb6ff71..7ae5fd052faf 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
@@ -13,6 +13,7 @@
 struct drm_printer;
 struct intel_engine_cs;
 
+void intel_guc_slpc_init_early(struct intel_guc *guc);
 void intel_guc_submission_init_early(struct intel_guc *guc);
 int intel_guc_submission_init(struct intel_guc *guc);
 void intel_guc_submission_enable(struct intel_guc *guc);
@@ -50,4 +51,19 @@ static inline bool intel_guc_submission_is_used(struct intel_guc *guc)
 	return intel_guc_is_used(guc) && intel_guc_submission_is_wanted(guc);
 }
 
+static inline bool intel_guc_slpc_is_supported(struct intel_guc *guc)
+{
+	return guc->slpc_supported;
+}
+
+static inline bool intel_guc_slpc_is_wanted(struct intel_guc *guc)
+{
+	return guc->slpc_selected;
+}
+
+static inline bool intel_guc_slpc_is_used(struct intel_guc *guc)
+{
+	return intel_guc_submission_is_used(guc) && intel_guc_slpc_is_wanted(guc);
+}
+
 #endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
index 61be0aa81492..dca5f6d0641b 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
@@ -76,16 +76,18 @@ static void __confirm_options(struct intel_uc *uc)
 	struct drm_i915_private *i915 = uc_to_gt(uc)->i915;
 
 	drm_dbg(&i915->drm,
-		"enable_guc=%d (guc:%s submission:%s huc:%s)\n",
+		"enable_guc=%d (guc:%s submission:%s huc:%s slpc:%s)\n",
 		i915->params.enable_guc,
 		yesno(intel_uc_wants_guc(uc)),
 		yesno(intel_uc_wants_guc_submission(uc)),
-		yesno(intel_uc_wants_huc(uc)));
+		yesno(intel_uc_wants_huc(uc)),
+		yesno(intel_uc_wants_guc_slpc(uc)));
 
 	if (i915->params.enable_guc == 0) {
 		GEM_BUG_ON(intel_uc_wants_guc(uc));
 		GEM_BUG_ON(intel_uc_wants_guc_submission(uc));
 		GEM_BUG_ON(intel_uc_wants_huc(uc));
+		GEM_BUG_ON(intel_uc_wants_guc_slpc(uc));
 		return;
 	}
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.h b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
index e2da2b6e76e1..38e465fd8a0c 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
@@ -83,6 +83,7 @@ __uc_state_checker(x, func, uses, used)
 uc_state_checkers(guc, guc);
 uc_state_checkers(huc, huc);
 uc_state_checkers(guc, guc_submission);
+uc_state_checkers(guc, guc_slpc);
 
 #undef uc_state_checkers
 #undef __uc_state_checker
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 03/16] drm/i915/guc/slpc: Gate Host RPS when slpc is enabled
  2021-07-10  1:20 [PATCH 00/16] Enable GuC based power management features Vinay Belgaumkar
  2021-07-10  1:20 ` [PATCH 02/16] drm/i915/guc/slpc: Initial definitions for slpc Vinay Belgaumkar
@ 2021-07-10  1:20 ` Vinay Belgaumkar
  2021-07-10  1:20 ` [PATCH 04/16] drm/i915/guc/slpc: Lay out slpc init/enable/disable/fini Vinay Belgaumkar
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 49+ messages in thread
From: Vinay Belgaumkar @ 2021-07-10  1:20 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Vinay Belgaumkar, Sundaresan Sujaritha

Disable RPS when slpc is enabled. Also ensure uc_init is called
before we initialize RPS so that we can check for slpc support.
We do not need to enable up/down interrupts when slpc is enabled.
However, we still need the ARAT interrupt, which will be enabled
separately.

Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
---
 drivers/gpu/drm/i915/gt/intel_gt.c  |  2 +-
 drivers/gpu/drm/i915/gt/intel_rps.c | 20 ++++++++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
index ceeb517ba259..f94d2e1ec3fe 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -41,8 +41,8 @@ void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915)
 	intel_gt_init_timelines(gt);
 	intel_gt_pm_init_early(gt);
 
-	intel_rps_init_early(&gt->rps);
 	intel_uc_init_early(&gt->uc);
+	intel_rps_init_early(&gt->rps);
 }
 
 int intel_gt_probe_lmem(struct intel_gt *gt)
diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c
index 0c8e7f2b06f0..e858eeb2c59d 100644
--- a/drivers/gpu/drm/i915/gt/intel_rps.c
+++ b/drivers/gpu/drm/i915/gt/intel_rps.c
@@ -37,6 +37,13 @@ static struct intel_uncore *rps_to_uncore(struct intel_rps *rps)
 	return rps_to_gt(rps)->uncore;
 }
 
+static bool rps_uses_slpc(struct intel_rps *rps)
+{
+	struct intel_gt *gt = rps_to_gt(rps);
+
+	return intel_uc_uses_guc_slpc(&gt->uc);
+}
+
 static u32 rps_pm_sanitize_mask(struct intel_rps *rps, u32 mask)
 {
 	return mask & ~rps->pm_intrmsk_mbz;
@@ -167,6 +174,8 @@ static void rps_enable_interrupts(struct intel_rps *rps)
 {
 	struct intel_gt *gt = rps_to_gt(rps);
 
+	GEM_BUG_ON(rps_uses_slpc(rps));
+
 	GT_TRACE(gt, "interrupts:on rps->pm_events: %x, rps_pm_mask:%x\n",
 		 rps->pm_events, rps_pm_mask(rps, rps->last_freq));
 
@@ -771,6 +780,8 @@ static int gen6_rps_set(struct intel_rps *rps, u8 val)
 	struct drm_i915_private *i915 = rps_to_i915(rps);
 	u32 swreq;
 
+	GEM_BUG_ON(rps_uses_slpc(rps));
+
 	if (GRAPHICS_VER(i915) >= 9)
 		swreq = GEN9_FREQUENCY(val);
 	else if (IS_HASWELL(i915) || IS_BROADWELL(i915))
@@ -861,6 +872,9 @@ void intel_rps_park(struct intel_rps *rps)
 {
 	int adj;
 
+	if (!intel_rps_is_enabled(rps))
+		return;
+
 	GEM_BUG_ON(atomic_read(&rps->num_waiters));
 
 	if (!intel_rps_clear_active(rps))
@@ -1829,6 +1843,9 @@ void intel_rps_init(struct intel_rps *rps)
 {
 	struct drm_i915_private *i915 = rps_to_i915(rps);
 
+	if (rps_uses_slpc(rps))
+		return;
+
 	if (IS_CHERRYVIEW(i915))
 		chv_rps_init(rps);
 	else if (IS_VALLEYVIEW(i915))
@@ -1885,6 +1902,9 @@ void intel_rps_init(struct intel_rps *rps)
 
 void intel_rps_sanitize(struct intel_rps *rps)
 {
+	if (rps_uses_slpc(rps))
+		return;
+
 	if (GRAPHICS_VER(rps_to_i915(rps)) >= 6)
 		rps_disable_interrupts(rps);
 }
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 04/16] drm/i915/guc/slpc: Lay out slpc init/enable/disable/fini
  2021-07-10  1:20 [PATCH 00/16] Enable GuC based power management features Vinay Belgaumkar
  2021-07-10  1:20 ` [PATCH 02/16] drm/i915/guc/slpc: Initial definitions for slpc Vinay Belgaumkar
  2021-07-10  1:20 ` [PATCH 03/16] drm/i915/guc/slpc: Gate Host RPS when slpc is enabled Vinay Belgaumkar
@ 2021-07-10  1:20 ` Vinay Belgaumkar
  2021-07-10 14:35   ` [Intel-gfx] " Michal Wajdeczko
  2021-07-10  1:20 ` [PATCH 05/16] drm/i915/guc/slpc: Adding slpc communication interfaces Vinay Belgaumkar
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 49+ messages in thread
From: Vinay Belgaumkar @ 2021-07-10  1:20 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Vinay Belgaumkar, Sundaresan Sujaritha

Declare header and source files for SLPC, along with init and
enable/disable function templates.

Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
---
 drivers/gpu/drm/i915/Makefile               |  1 +
 drivers/gpu/drm/i915/gt/uc/intel_guc.h      |  2 ++
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 34 +++++++++++++++++++++
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 16 ++++++++++
 4 files changed, 53 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index ab7679957623..d8eac4468df9 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -186,6 +186,7 @@ i915-y += gt/uc/intel_uc.o \
 	  gt/uc/intel_guc_fw.o \
 	  gt/uc/intel_guc_log.o \
 	  gt/uc/intel_guc_log_debugfs.o \
+	  gt/uc/intel_guc_slpc.o \
 	  gt/uc/intel_guc_submission.o \
 	  gt/uc/intel_huc.o \
 	  gt/uc/intel_huc_debugfs.o \
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
index e5a456918b88..0dbbd9cf553f 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
@@ -15,6 +15,7 @@
 #include "intel_guc_ct.h"
 #include "intel_guc_log.h"
 #include "intel_guc_reg.h"
+#include "intel_guc_slpc.h"
 #include "intel_uc_fw.h"
 #include "i915_utils.h"
 #include "i915_vma.h"
@@ -30,6 +31,7 @@ struct intel_guc {
 	struct intel_uc_fw fw;
 	struct intel_guc_log log;
 	struct intel_guc_ct ct;
+	struct intel_guc_slpc slpc;
 
 	/* Global engine used to submit requests to GuC */
 	struct i915_sched_engine *sched_engine;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
new file mode 100644
index 000000000000..c1f569d2300d
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -0,0 +1,34 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include "intel_guc_slpc.h"
+
+int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
+{
+	return 0;
+}
+
+/*
+ * intel_guc_slpc_enable() - Start SLPC
+ * @slpc: pointer to intel_guc_slpc.
+ *
+ * SLPC is enabled by setting up the shared data structure and
+ * sending reset event to GuC SLPC. Initial data is setup in
+ * intel_guc_slpc_init. Here we send the reset event. We do
+ * not currently need a slpc_disable since this is taken care
+ * of automatically when a reset/suspend occurs and the guc
+ * channels are destroyed.
+ *
+ * Return: 0 on success, non-zero error code on failure.
+ */
+int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
+{
+	return 0;
+}
+
+void intel_guc_slpc_fini(struct intel_guc_slpc *slpc)
+{
+}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
new file mode 100644
index 000000000000..74fd86769163
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
@@ -0,0 +1,16 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2020 Intel Corporation
+ */
+#ifndef _INTEL_GUC_SLPC_H_
+#define _INTEL_GUC_SLPC_H_
+
+struct intel_guc_slpc {
+};
+
+int intel_guc_slpc_init(struct intel_guc_slpc *slpc);
+int intel_guc_slpc_enable(struct intel_guc_slpc *slpc);
+void intel_guc_slpc_fini(struct intel_guc_slpc *slpc);
+
+#endif
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 05/16] drm/i915/guc/slpc: Adding slpc communication interfaces
  2021-07-10  1:20 [PATCH 00/16] Enable GuC based power management features Vinay Belgaumkar
                   ` (2 preceding siblings ...)
  2021-07-10  1:20 ` [PATCH 04/16] drm/i915/guc/slpc: Lay out slpc init/enable/disable/fini Vinay Belgaumkar
@ 2021-07-10  1:20 ` Vinay Belgaumkar
  2021-07-10 15:52   ` Michal Wajdeczko
  2021-07-10  1:20 ` [PATCH 06/16] drm/i915/guc/slpc: Allocate, initialize and release slpc Vinay Belgaumkar
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 49+ messages in thread
From: Vinay Belgaumkar @ 2021-07-10  1:20 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Vinay Belgaumkar, Sundaresan Sujaritha

Replicate the SLPC header file in GuC for the most part. There are
some SLPC mode based parameters which haven't been included since
we are not using them.

Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
---
 drivers/gpu/drm/i915/gt/uc/intel_guc.c        |   4 +
 drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h   |   2 +
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h   |   2 +
 .../gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h  | 255 ++++++++++++++++++
 4 files changed, 263 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index b9a809f2d221..9d61b2d54de4 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -202,11 +202,15 @@ static u32 guc_ctl_debug_flags(struct intel_guc *guc)
 
 static u32 guc_ctl_feature_flags(struct intel_guc *guc)
 {
+	struct intel_gt *gt = guc_to_gt(guc);
 	u32 flags = 0;
 
 	if (!intel_guc_submission_is_used(guc))
 		flags |= GUC_CTL_DISABLE_SCHEDULER;
 
+	if (intel_uc_uses_guc_slpc(&gt->uc))
+		flags |= GUC_CTL_ENABLE_SLPC;
+
 	return flags;
 }
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
index 94bb1ca6f889..19e2504d7a36 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
@@ -114,6 +114,8 @@
 #define   GUC_ADS_ADDR_SHIFT		1
 #define   GUC_ADS_ADDR_MASK		(0xFFFFF << GUC_ADS_ADDR_SHIFT)
 
+#define GUC_CTL_ENABLE_SLPC            BIT(2)
+
 #define GUC_CTL_MAX_DWORDS		(SOFT_SCRATCH_COUNT - 2) /* [1..14] */
 
 /* Generic GT SysInfo data types */
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
index 74fd86769163..98036459a1a3 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
@@ -6,6 +6,8 @@
 #ifndef _INTEL_GUC_SLPC_H_
 #define _INTEL_GUC_SLPC_H_
 
+#include "intel_guc_slpc_fwif.h"
+
 struct intel_guc_slpc {
 };
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h
new file mode 100644
index 000000000000..2a5e71428374
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h
@@ -0,0 +1,255 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2020 Intel Corporation
+ */
+#ifndef _INTEL_GUC_SLPC_FWIF_H_
+#define _INTEL_GUC_SLPC_FWIF_H_
+
+#include <linux/types.h>
+
+/* This file replicates the header in GuC code for handling SLPC related
+ * data structures and sizes
+ */
+
+/* SLPC exposes certain parameters for global configuration by the host.
+ * These are referred to as override parameters, because in most cases
+ * the host will not need to modify the default values used by SLPC.
+ * SLPC remembers the default values which allows the host to easily restore
+ * them by simply unsetting the override. The host can set or unset override
+ * parameters during SLPC (re-)initialization using the SLPC Reset event.
+ * The host can also set or unset override parameters on the fly using the
+ * Parameter Set and Parameter Unset events
+ */
+#define SLPC_MAX_OVERRIDE_PARAMETERS	256
+#define SLPC_OVERRIDE_BITFIELD_SIZE \
+		(SLPC_MAX_OVERRIDE_PARAMETERS / 32)
+
+#define SLPC_PAGE_SIZE_BYTES			4096
+#define SLPC_CACHELINE_SIZE_BYTES		64
+#define SLPC_SHARE_DATA_SIZE_BYTE_HEADER	SLPC_CACHELINE_SIZE_BYTES
+#define SLPC_SHARE_DATA_SIZE_BYTE_PLATFORM_INFO	SLPC_CACHELINE_SIZE_BYTES
+#define SLPC_SHARE_DATA_SIZE_BYTE_TASK_STATE	SLPC_CACHELINE_SIZE_BYTES
+#define SLPC_SHARE_DATA_MODE_DEFN_TABLE_SIZE	SLPC_PAGE_SIZE_BYTES
+
+#define SLPC_SHARE_DATA_SIZE_BYTE_MAX		(2 * SLPC_PAGE_SIZE_BYTES)
+
+/* Cacheline size aligned (Total size needed for
+ * SLPM_KMD_MAX_OVERRIDE_PARAMETERS=256 is 1088 bytes)
+ */
+#define SLPC_SHARE_DATA_SIZE_BYTE_PARAM		(((((SLPC_MAX_OVERRIDE_PARAMETERS * 4) \
+						+ ((SLPC_MAX_OVERRIDE_PARAMETERS / 32) * 4)) \
+		+ (SLPC_CACHELINE_SIZE_BYTES-1)) / SLPC_CACHELINE_SIZE_BYTES)*SLPC_CACHELINE_SIZE_BYTES)
+
+#define SLPC_SHARE_DATA_SIZE_BYTE_OTHER		(SLPC_SHARE_DATA_SIZE_BYTE_MAX - \
+					(SLPC_SHARE_DATA_SIZE_BYTE_HEADER \
+					+ SLPC_SHARE_DATA_SIZE_BYTE_PLATFORM_INFO \
+					+ SLPC_SHARE_DATA_SIZE_BYTE_TASK_STATE \
+					+ SLPC_SHARE_DATA_SIZE_BYTE_PARAM \
+					+ SLPC_SHARE_DATA_MODE_DEFN_TABLE_SIZE))
+
+#define SLPC_EVENT(id, argc)			((u32)(id) << 8 | (argc))
+
+#define SLPC_PARAM_TASK_DEFAULT			0
+#define SLPC_PARAM_TASK_ENABLED			1
+#define SLPC_PARAM_TASK_DISABLED		2
+#define SLPC_PARAM_TASK_UNKNOWN			3
+
+enum slpc_status {
+	SLPC_STATUS_OK = 0,
+	SLPC_STATUS_ERROR = 1,
+	SLPC_STATUS_ILLEGAL_COMMAND = 2,
+	SLPC_STATUS_INVALID_ARGS = 3,
+	SLPC_STATUS_INVALID_PARAMS = 4,
+	SLPC_STATUS_INVALID_DATA = 5,
+	SLPC_STATUS_OUT_OF_RANGE = 6,
+	SLPC_STATUS_NOT_SUPPORTED = 7,
+	SLPC_STATUS_NOT_IMPLEMENTED = 8,
+	SLPC_STATUS_NO_DATA = 9,
+	SLPC_STATUS_EVENT_NOT_REGISTERED = 10,
+	SLPC_STATUS_REGISTER_LOCKED = 11,
+	SLPC_STATUS_TEMPORARILY_UNAVAILABLE = 12,
+	SLPC_STATUS_VALUE_ALREADY_SET = 13,
+	SLPC_STATUS_VALUE_ALREADY_UNSET = 14,
+	SLPC_STATUS_VALUE_NOT_CHANGED = 15,
+	SLPC_STATUS_MEMIO_ERROR = 16,
+	SLPC_STATUS_EVENT_QUEUED_REQ_DPC = 17,
+	SLPC_STATUS_EVENT_QUEUED_NOREQ_DPC = 18,
+	SLPC_STATUS_NO_EVENT_QUEUED = 19,
+	SLPC_STATUS_OUT_OF_SPACE = 20,
+	SLPC_STATUS_TIMEOUT = 21,
+	SLPC_STATUS_NO_LOCK = 22,
+	SLPC_STATUS_MAX
+};
+
+enum slpc_event_id {
+	SLPC_EVENT_RESET = 0,
+	SLPC_EVENT_SHUTDOWN = 1,
+	SLPC_EVENT_PLATFORM_INFO_CHANGE = 2,
+	SLPC_EVENT_DISPLAY_MODE_CHANGE = 3,
+	SLPC_EVENT_FLIP_COMPLETE = 4,
+	SLPC_EVENT_QUERY_TASK_STATE = 5,
+	SLPC_EVENT_PARAMETER_SET = 6,
+	SLPC_EVENT_PARAMETER_UNSET = 7,
+};
+
+enum slpc_param_id {
+	SLPC_PARAM_TASK_ENABLE_GTPERF = 0,
+	SLPC_PARAM_TASK_DISABLE_GTPERF = 1,
+	SLPC_PARAM_TASK_ENABLE_BALANCER = 2,
+	SLPC_PARAM_TASK_DISABLE_BALANCER = 3,
+	SLPC_PARAM_TASK_ENABLE_DCC = 4,
+	SLPC_PARAM_TASK_DISABLE_DCC = 5,
+	SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ = 6,
+	SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ = 7,
+	SLPC_PARAM_GLOBAL_MIN_GT_SLICE_FREQ_MHZ = 8,
+	SLPC_PARAM_GLOBAL_MAX_GT_SLICE_FREQ_MHZ = 9,
+	SLPC_PARAM_GTPERF_THRESHOLD_MAX_FPS = 10,
+	SLPC_PARAM_GLOBAL_DISABLE_GT_FREQ_MANAGEMENT = 11,
+	SLPC_PARAM_GTPERF_ENABLE_FRAMERATE_STALLING = 12,
+	SLPC_PARAM_GLOBAL_DISABLE_RC6_MODE_CHANGE = 13,
+	SLPC_PARAM_GLOBAL_OC_UNSLICE_FREQ_MHZ = 14,
+	SLPC_PARAM_GLOBAL_OC_SLICE_FREQ_MHZ = 15,
+	SLPC_PARAM_GLOBAL_ENABLE_IA_GT_BALANCING = 16,
+	SLPC_PARAM_GLOBAL_ENABLE_ADAPTIVE_BURST_TURBO = 17,
+	SLPC_PARAM_GLOBAL_ENABLE_EVAL_MODE = 18,
+	SLPC_PARAM_GLOBAL_ENABLE_BALANCER_IN_NON_GAMING_MODE = 19,
+	SLPC_PARAM_GLOBAL_RT_MODE_TURBO_FREQ_DELTA_MHZ = 20,
+	SLPC_PARAM_PWRGATE_RC_MODE = 21,
+	SLPC_PARAM_EDR_MODE_COMPUTE_TIMEOUT_MS = 22,
+	SLPC_PARAM_EDR_QOS_FREQ_MHZ = 23,
+	SLPC_PARAM_MEDIA_FF_RATIO_MODE = 24,
+	SLPC_PARAM_ENABLE_IA_FREQ_LIMITING = 25,
+	SLPC_PARAM_STRATEGIES = 26,
+	SLPC_PARAM_POWER_PROFILE = 27,
+	SLPC_IGNORE_EFFICIENT_FREQUENCY = 28,
+	SLPC_MAX_PARAM = 32,
+};
+
+enum slpc_global_state {
+	SLPC_GLOBAL_STATE_NOT_RUNNING = 0,
+	SLPC_GLOBAL_STATE_INITIALIZING = 1,
+	SLPC_GLOBAL_STATE_RESETTING = 2,
+	SLPC_GLOBAL_STATE_RUNNING = 3,
+	SLPC_GLOBAL_STATE_SHUTTING_DOWN = 4,
+	SLPC_GLOBAL_STATE_ERROR = 5
+};
+
+enum slpc_platform_sku {
+	SLPC_PLATFORM_SKU_UNDEFINED = 0,
+	SLPC_PLATFORM_SKU_ULX = 1,
+	SLPC_PLATFORM_SKU_ULT = 2,
+	SLPC_PLATFORM_SKU_T = 3,
+	SLPC_PLATFORM_SKU_MOBL = 4,
+	SLPC_PLATFORM_SKU_DT = 5,
+	SLPC_PLATFORM_SKU_UNKNOWN = 6,
+};
+
+struct slpc_platform_info {
+	union {
+		u32 sku;  /**< SKU info */
+		struct {
+			u32 reserved:8;
+			u32 fused_slice_count:8;
+			u32 reserved1:16;
+		};
+	};
+        union
+	{
+		u32 bitfield2;       /**< IA capability info*/
+		struct {
+			u32 max_p0_freq_bins:8;
+			u32 p1_freq_bins:8;
+			u32 pe_freq_bins:8;
+			u32 pn_freq_bins:8;
+		};
+	};
+	u32 reserved2[2];
+} __packed;
+
+struct slpc_task_state_data {
+	union {
+		u32 bitfield1;
+		struct {
+			u32 gtperf_task_active:1;
+			u32 gtperf_stall_possible:1;
+			u32 gtperf_gaming_mode:1;
+			u32 gtperf_target_fps:8;
+			u32 dcc_task_active:1;
+			u32 in_dcc:1;
+			u32 in_dct:1;
+			u32 freq_switch_active:1;
+			u32 ibc_enabled:1;
+			u32 ibc_active:1;
+			u32 pg1_enabled:1;
+			u32 pg1_active:1;
+		};
+	};
+	union {
+		u32 bitfield2;
+		struct {
+			u32 max_unslice_freq:8;
+			u32 min_unslice_freq:8;
+			u32 max_slice_freq:8;
+			u32 min_slice_freq:8;
+		};
+	};
+} __packed;
+
+struct slpc_shared_data {
+	union {
+		struct {
+			/* Total size in bytes of this buffer. */
+			u32 shared_data_size;
+			u32 global_state;
+			u32 display_data_addr;
+		};
+		unsigned char reserved_header[SLPC_SHARE_DATA_SIZE_BYTE_HEADER];
+	};
+
+	union {
+		struct slpc_platform_info platform_info;
+		unsigned char reserved_platform[SLPC_SHARE_DATA_SIZE_BYTE_PLATFORM_INFO];
+	};
+
+	union {
+		struct slpc_task_state_data task_state_data;
+		unsigned char reserved_task_state[SLPC_SHARE_DATA_SIZE_BYTE_TASK_STATE];
+	};
+
+	union {
+		struct {
+		u32 override_params_set_bits[SLPC_OVERRIDE_BITFIELD_SIZE];
+		u32 override_params_values[SLPC_MAX_OVERRIDE_PARAMETERS];
+		};
+		unsigned char reserved_override_parameter[SLPC_SHARE_DATA_SIZE_BYTE_PARAM];
+	};
+
+	unsigned char reserved_other[SLPC_SHARE_DATA_SIZE_BYTE_OTHER];
+
+	/* PAGE 2 (4096 bytes), mode based parameter will be removed soon */
+	unsigned char reserved_mode_definition[4096];
+} __packed;
+
+enum slpc_reset_flags {
+	SLPC_RESET_FLAG_TDR_OCCURRED = (1 << 0)
+};
+
+#define SLPC_EVENT_MAX_INPUT_ARGS  9
+#define SLPC_EVENT_MAX_OUTPUT_ARGS 1
+
+union slpc_event_input_header {
+	u32 value;
+	struct {
+		u32 num_args:8;
+		u32 event_id:8;
+	};
+};
+
+struct slpc_event_input {
+	u32 h2g_action_id;
+	union slpc_event_input_header header;
+	u32 args[SLPC_EVENT_MAX_INPUT_ARGS];
+} __packed;
+
+#endif
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 06/16] drm/i915/guc/slpc: Allocate, initialize and release slpc
  2021-07-10  1:20 [PATCH 00/16] Enable GuC based power management features Vinay Belgaumkar
                   ` (3 preceding siblings ...)
  2021-07-10  1:20 ` [PATCH 05/16] drm/i915/guc/slpc: Adding slpc communication interfaces Vinay Belgaumkar
@ 2021-07-10  1:20 ` Vinay Belgaumkar
  2021-07-10 16:05   ` Michal Wajdeczko
  2021-07-10  1:20 ` [PATCH 07/16] drm/i915/guc/slpc: Enable slpc and add related H2G events Vinay Belgaumkar
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 49+ messages in thread
From: Vinay Belgaumkar @ 2021-07-10  1:20 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Vinay Belgaumkar, Sundaresan Sujaritha

Allocate data structures for SLPC and functions for
initializing on host side.

Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
---
 drivers/gpu/drm/i915/gt/uc/intel_guc.c      | 11 +++++++
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 36 ++++++++++++++++++++-
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 20 ++++++++++++
 3 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index 9d61b2d54de4..82863a9bc8e8 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -336,6 +336,12 @@ int intel_guc_init(struct intel_guc *guc)
 			goto err_ct;
 	}
 
+	if (intel_guc_slpc_is_used(guc)) {
+		ret = intel_guc_slpc_init(&guc->slpc);
+		if (ret)
+			goto err_submission;
+	}
+
 	/* now that everything is perma-pinned, initialize the parameters */
 	guc_init_params(guc);
 
@@ -346,6 +352,8 @@ int intel_guc_init(struct intel_guc *guc)
 
 	return 0;
 
+err_submission:
+	intel_guc_submission_fini(guc);
 err_ct:
 	intel_guc_ct_fini(&guc->ct);
 err_ads:
@@ -368,6 +376,9 @@ void intel_guc_fini(struct intel_guc *guc)
 
 	i915_ggtt_disable_guc(gt->ggtt);
 
+	if (intel_guc_slpc_is_used(guc))
+		intel_guc_slpc_fini(&guc->slpc);
+
 	if (intel_guc_submission_is_used(guc))
 		intel_guc_submission_fini(guc);
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
index c1f569d2300d..94e2f19951aa 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -4,11 +4,41 @@
  * Copyright © 2020 Intel Corporation
  */
 
+#include <asm/msr-index.h>
+
+#include "gt/intel_gt.h"
+#include "gt/intel_rps.h"
+
+#include "i915_drv.h"
 #include "intel_guc_slpc.h"
+#include "intel_pm.h"
+
+static inline struct intel_guc *slpc_to_guc(struct intel_guc_slpc *slpc)
+{
+	return container_of(slpc, struct intel_guc, slpc);
+}
+
+static int slpc_shared_data_init(struct intel_guc_slpc *slpc)
+{
+	struct intel_guc *guc = slpc_to_guc(slpc);
+	int err;
+	u32 size = PAGE_ALIGN(sizeof(struct slpc_shared_data));
+
+	err = intel_guc_allocate_and_map_vma(guc, size, &slpc->vma, &slpc->vaddr);
+	if (unlikely(err)) {
+		DRM_ERROR("Failed to allocate slpc struct (err=%d)\n", err);
+		i915_vma_unpin_and_release(&slpc->vma, I915_VMA_RELEASE_MAP);
+		return err;
+	}
+
+	return err;
+}
 
 int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
 {
-	return 0;
+	GEM_BUG_ON(slpc->vma);
+
+	return slpc_shared_data_init(slpc);
 }
 
 /*
@@ -31,4 +61,8 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
 
 void intel_guc_slpc_fini(struct intel_guc_slpc *slpc)
 {
+	if (!slpc->vma)
+		return;
+
+	i915_vma_unpin_and_release(&slpc->vma, I915_VMA_RELEASE_MAP);
 }
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
index 98036459a1a3..a2643b904165 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
@@ -3,12 +3,32 @@
  *
  * Copyright © 2020 Intel Corporation
  */
+
 #ifndef _INTEL_GUC_SLPC_H_
 #define _INTEL_GUC_SLPC_H_
 
+#include <linux/mutex.h>
 #include "intel_guc_slpc_fwif.h"
 
 struct intel_guc_slpc {
+	/*Protects access to vma and SLPC actions */
+	struct i915_vma *vma;
+	void *vaddr;
+
+	/* platform frequency limits */
+	u32 min_freq;
+	u32 rp0_freq;
+	u32 rp1_freq;
+
+	/* frequency softlimits */
+	u32 min_freq_softlimit;
+	u32 max_freq_softlimit;
+
+	struct {
+		u32 param_id;
+		u32 param_value;
+		u32 param_override;
+	} debug;
 };
 
 int intel_guc_slpc_init(struct intel_guc_slpc *slpc);
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 07/16] drm/i915/guc/slpc: Enable slpc and add related H2G events
  2021-07-10  1:20 [PATCH 00/16] Enable GuC based power management features Vinay Belgaumkar
                   ` (4 preceding siblings ...)
  2021-07-10  1:20 ` [PATCH 06/16] drm/i915/guc/slpc: Allocate, initialize and release slpc Vinay Belgaumkar
@ 2021-07-10  1:20 ` Vinay Belgaumkar
  2021-07-10 17:37   ` [Intel-gfx] " Michal Wajdeczko
  2021-07-10  1:20 ` [PATCH 08/16] drm/i915/guc/slpc: Add methods to set min/max frequency Vinay Belgaumkar
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 49+ messages in thread
From: Vinay Belgaumkar @ 2021-07-10  1:20 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Vinay Belgaumkar, Sundaresan Sujaritha

Add methods for interacting with guc for enabling SLPC. Enable
SLPC after guc submission has been established. GuC load will
fail if SLPC cannot be successfully initialized. Add various
helper methods to set/unset the parameters for SLPC. They can
be set using h2g calls or directly setting bits in the shared
data structure.

Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
---
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c   | 221 ++++++++++++++++++
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c |   4 -
 drivers/gpu/drm/i915/gt/uc/intel_uc.c         |  10 +
 3 files changed, 231 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
index 94e2f19951aa..e579408d1c19 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -18,6 +18,61 @@ static inline struct intel_guc *slpc_to_guc(struct intel_guc_slpc *slpc)
 	return container_of(slpc, struct intel_guc, slpc);
 }
 
+static inline struct intel_gt *slpc_to_gt(struct intel_guc_slpc *slpc)
+{
+	return guc_to_gt(slpc_to_guc(slpc));
+}
+
+static inline struct drm_i915_private *slpc_to_i915(struct intel_guc_slpc *slpc)
+{
+	return (slpc_to_gt(slpc))->i915;
+}
+
+static void slpc_mem_set_param(struct slpc_shared_data *data,
+				u32 id, u32 value)
+{
+	GEM_BUG_ON(id >= SLPC_MAX_OVERRIDE_PARAMETERS);
+	/* When the flag bit is set, corresponding value will be read
+	 * and applied by slpc.
+	 */
+	data->override_params_set_bits[id >> 5] |= (1 << (id % 32));
+	data->override_params_values[id] = value;
+}
+
+static void slpc_mem_unset_param(struct slpc_shared_data *data,
+				 u32 id)
+{
+	GEM_BUG_ON(id >= SLPC_MAX_OVERRIDE_PARAMETERS);
+	/* When the flag bit is unset, corresponding value will not be
+	 * read by slpc.
+	 */
+	data->override_params_set_bits[id >> 5] &= (~(1 << (id % 32)));
+	data->override_params_values[id] = 0;
+}
+
+static void slpc_mem_task_control(struct slpc_shared_data *data,
+				 u64 val, u32 enable_id, u32 disable_id)
+{
+	/* Enabling a param involves setting the enable_id
+	 * to 1 and disable_id to 0. Setting it to default
+	 * will unset both enable and disable ids and let
+	 * slpc choose it's default values.
+	 */
+	if (val == SLPC_PARAM_TASK_DEFAULT) {
+		/* set default */
+		slpc_mem_unset_param(data, enable_id);
+		slpc_mem_unset_param(data, disable_id);
+	} else if (val == SLPC_PARAM_TASK_ENABLED) {
+		/* set enable */
+		slpc_mem_set_param(data, enable_id, 1);
+		slpc_mem_set_param(data, disable_id, 0);
+	} else if (val == SLPC_PARAM_TASK_DISABLED) {
+		/* set disable */
+		slpc_mem_set_param(data, disable_id, 1);
+		slpc_mem_set_param(data, enable_id, 0);
+	}
+}
+
 static int slpc_shared_data_init(struct intel_guc_slpc *slpc)
 {
 	struct intel_guc *guc = slpc_to_guc(slpc);
@@ -34,6 +89,128 @@ static int slpc_shared_data_init(struct intel_guc_slpc *slpc)
 	return err;
 }
 
+/*
+ * Send SLPC event to guc
+ *
+ */
+static int slpc_send(struct intel_guc_slpc *slpc,
+			struct slpc_event_input *input,
+			u32 in_len)
+{
+	struct intel_guc *guc = slpc_to_guc(slpc);
+	u32 *action;
+
+	action = (u32 *)input;
+	action[0] = INTEL_GUC_ACTION_SLPC_REQUEST;
+
+	return intel_guc_send(guc, action, in_len);
+}
+
+static bool slpc_running(struct intel_guc_slpc *slpc)
+{
+	struct slpc_shared_data *data;
+	u32 slpc_global_state;
+
+	GEM_BUG_ON(!slpc->vma);
+
+	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));
+	data = slpc->vaddr;
+
+	slpc_global_state = data->global_state;
+
+	return (data->global_state == SLPC_GLOBAL_STATE_RUNNING);
+}
+
+static int host2guc_slpc_query_task_state(struct intel_guc_slpc *slpc)
+{
+	struct intel_guc *guc = slpc_to_guc(slpc);
+	u32 shared_data_gtt_offset = intel_guc_ggtt_offset(guc, slpc->vma);
+	struct slpc_event_input data = {0};
+
+	data.header.value = SLPC_EVENT(SLPC_EVENT_QUERY_TASK_STATE, 2);
+	data.args[0] = shared_data_gtt_offset;
+	data.args[1] = 0;
+
+	return slpc_send(slpc, &data, 4);
+}
+
+static int slpc_read_task_state(struct intel_guc_slpc *slpc)
+{
+	return host2guc_slpc_query_task_state(slpc);
+}
+
+static const char *slpc_state_stringify(enum slpc_global_state state)
+{
+	const char *str = NULL;
+
+	switch (state) {
+	case SLPC_GLOBAL_STATE_NOT_RUNNING:
+		str = "not running";
+		break;
+	case SLPC_GLOBAL_STATE_INITIALIZING:
+		str = "initializing";
+		break;
+	case SLPC_GLOBAL_STATE_RESETTING:
+		str = "resetting";
+		break;
+	case SLPC_GLOBAL_STATE_RUNNING:
+		str = "running";
+		break;
+	case SLPC_GLOBAL_STATE_SHUTTING_DOWN:
+		str = "shutting down";
+		break;
+	case SLPC_GLOBAL_STATE_ERROR:
+		str = "error";
+		break;
+	default:
+		str = "unknown";
+		break;
+	}
+
+	return str;
+}
+
+static const char *get_slpc_state(struct intel_guc_slpc *slpc)
+{
+	struct slpc_shared_data *data;
+	u32 slpc_global_state;
+
+	GEM_BUG_ON(!slpc->vma);
+
+	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));
+	data = slpc->vaddr;
+
+	slpc_global_state = data->global_state;
+
+	return slpc_state_stringify(slpc_global_state);
+}
+
+static int host2guc_slpc_reset(struct intel_guc_slpc *slpc)
+{
+	struct intel_guc *guc = slpc_to_guc(slpc);
+	u32 shared_data_gtt_offset = intel_guc_ggtt_offset(guc, slpc->vma);
+	struct slpc_event_input data = {0};
+	int ret;
+
+	data.header.value = SLPC_EVENT(SLPC_EVENT_RESET, 2);
+	data.args[0] = shared_data_gtt_offset;
+	data.args[1] = 0;
+
+	/* TODO: Hardcoded 4 needs define */
+	ret = slpc_send(slpc, &data, 4);
+
+	if (!ret) {
+		/* TODO: How long to Wait until SLPC is running */
+		if (wait_for(slpc_running(slpc), 5)) {
+			DRM_ERROR("SLPC not enabled! State = %s\n",
+				  get_slpc_state(slpc));
+			return -EIO;
+		}
+	}
+
+	return ret;
+}
+
 int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
 {
 	GEM_BUG_ON(slpc->vma);
@@ -56,6 +233,50 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
  */
 int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
 {
+	struct drm_i915_private *i915 = slpc_to_i915(slpc);
+	struct slpc_shared_data *data;
+	int ret;
+
+	GEM_BUG_ON(!slpc->vma);
+
+	memset(slpc->vaddr, 0, sizeof(struct slpc_shared_data));
+
+	data = slpc->vaddr;
+	data->shared_data_size = sizeof(struct slpc_shared_data);
+
+	/* Enable only GTPERF task, Disable others */
+	slpc_mem_task_control(data, SLPC_PARAM_TASK_ENABLED,
+				SLPC_PARAM_TASK_ENABLE_GTPERF,
+				SLPC_PARAM_TASK_DISABLE_GTPERF);
+
+	slpc_mem_task_control(data, SLPC_PARAM_TASK_DISABLED,
+				SLPC_PARAM_TASK_ENABLE_BALANCER,
+				SLPC_PARAM_TASK_DISABLE_BALANCER);
+
+	slpc_mem_task_control(data, SLPC_PARAM_TASK_DISABLED,
+				SLPC_PARAM_TASK_ENABLE_DCC,
+				SLPC_PARAM_TASK_DISABLE_DCC);
+
+	ret = host2guc_slpc_reset(slpc);
+	if (ret) {
+		drm_err(&i915->drm, "SLPC Reset event returned %d", ret);
+		return -EIO;
+	}
+
+	DRM_INFO("SLPC state: %s\n", get_slpc_state(slpc));
+
+	if (slpc_read_task_state(slpc))
+		drm_err(&i915->drm, "Unable to read task state data");
+
+	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));
+
+	/* min and max frequency limits being used by SLPC */
+	drm_info(&i915->drm, "SLPC min freq: %u Mhz, max is %u Mhz",
+			DIV_ROUND_CLOSEST(data->task_state_data.min_unslice_freq *
+				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER),
+			DIV_ROUND_CLOSEST(data->task_state_data.max_unslice_freq *
+				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER));
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
index e2644a05f298..3e76d4d5f7bb 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
@@ -2321,10 +2321,6 @@ void intel_guc_submission_enable(struct intel_guc *guc)
 
 void intel_guc_submission_disable(struct intel_guc *guc)
 {
-	struct intel_gt *gt = guc_to_gt(guc);
-
-	GEM_BUG_ON(gt->awake); /* GT should be parked first */
-
 	/* Note: By the time we're here, GuC may have already been reset */
 }
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
index dca5f6d0641b..7b6c767d3eb0 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
@@ -501,6 +501,14 @@ static int __uc_init_hw(struct intel_uc *uc)
 	if (intel_uc_uses_guc_submission(uc))
 		intel_guc_submission_enable(guc);
 
+	if (intel_uc_uses_guc_slpc(uc)) {
+		ret = intel_guc_slpc_enable(&guc->slpc);
+		if (ret)
+			goto err_submission;
+		drm_info(&i915->drm, "GuC SLPC %s\n",
+			 enableddisabled(intel_uc_uses_guc_slpc(uc)));
+	}
+
 	drm_info(&i915->drm, "%s firmware %s version %u.%u %s:%s\n",
 		 intel_uc_fw_type_repr(INTEL_UC_FW_TYPE_GUC), guc->fw.path,
 		 guc->fw.major_ver_found, guc->fw.minor_ver_found,
@@ -521,6 +529,8 @@ static int __uc_init_hw(struct intel_uc *uc)
 	/*
 	 * We've failed to load the firmware :(
 	 */
+err_submission:
+	intel_guc_submission_disable(guc);
 err_log_capture:
 	__uc_capture_load_err_log(uc);
 err_out:
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 08/16] drm/i915/guc/slpc: Add methods to set min/max frequency
  2021-07-10  1:20 [PATCH 00/16] Enable GuC based power management features Vinay Belgaumkar
                   ` (5 preceding siblings ...)
  2021-07-10  1:20 ` [PATCH 07/16] drm/i915/guc/slpc: Enable slpc and add related H2G events Vinay Belgaumkar
@ 2021-07-10  1:20 ` Vinay Belgaumkar
  2021-07-10  3:07   ` kernel test robot
                     ` (2 more replies)
  2021-07-10  1:20 ` [PATCH 09/16] drm/i915/guc/slpc: Add get max/min freq hooks Vinay Belgaumkar
                   ` (7 subsequent siblings)
  14 siblings, 3 replies; 49+ messages in thread
From: Vinay Belgaumkar @ 2021-07-10  1:20 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Vinay Belgaumkar, Sundaresan Sujaritha

Add param set h2g helpers to set the min and max frequencies
for use by SLPC.

Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
---
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 94 +++++++++++++++++++++
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h |  2 +
 2 files changed, 96 insertions(+)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
index e579408d1c19..19cb26479942 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -106,6 +106,19 @@ static int slpc_send(struct intel_guc_slpc *slpc,
 	return intel_guc_send(guc, action, in_len);
 }
 
+static int host2guc_slpc_set_param(struct intel_guc_slpc *slpc,
+				   u32 id, u32 value)
+{
+	struct slpc_event_input data = {0};
+
+	data.header.value = SLPC_EVENT(SLPC_EVENT_PARAMETER_SET, 2);
+	data.args[0] = id;
+	data.args[1] = value;
+
+	return slpc_send(slpc, &data, 4);
+}
+
+
 static bool slpc_running(struct intel_guc_slpc *slpc)
 {
 	struct slpc_shared_data *data;
@@ -134,6 +147,19 @@ static int host2guc_slpc_query_task_state(struct intel_guc_slpc *slpc)
 	return slpc_send(slpc, &data, 4);
 }
 
+static int slpc_set_param(struct intel_guc_slpc *slpc, u32 id, u32 value)
+{
+	struct drm_i915_private *i915 = slpc_to_i915(slpc);
+	GEM_BUG_ON(id >= SLPC_MAX_PARAM);
+
+	if (host2guc_slpc_set_param(slpc, id, value)) {
+		drm_err(&i915->drm, "Unable to set param %x", id);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static int slpc_read_task_state(struct intel_guc_slpc *slpc)
 {
 	return host2guc_slpc_query_task_state(slpc);
@@ -218,6 +244,74 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
 	return slpc_shared_data_init(slpc);
 }
 
+/**
+ * intel_guc_slpc_max_freq_set() - Set max frequency limit for SLPC.
+ * @slpc: pointer to intel_guc_slpc.
+ * @val: encoded frequency
+ *
+ * This function will invoke GuC SLPC action to update the max frequency
+ * limit for slice and unslice.
+ *
+ * Return: 0 on success, non-zero error code on failure.
+ */
+int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val)
+{
+	int ret;
+	struct drm_i915_private *i915 = slpc_to_i915(slpc);
+	intel_wakeref_t wakeref;
+
+	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
+
+	ret = slpc_set_param(slpc,
+		       SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ,
+		       val);
+
+	if (ret) {
+		drm_err(&i915->drm,
+			"Set max frequency unslice returned %d", ret);
+		ret = -EIO;
+		goto done;
+	}
+
+done:
+	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
+	return ret;
+}
+
+/**
+ * intel_guc_slpc_min_freq_set() - Set min frequency limit for SLPC.
+ * @slpc: pointer to intel_guc_slpc.
+ * @val: encoded frequency
+ *
+ * This function will invoke GuC SLPC action to update the min frequency
+ * limit.
+ *
+ * Return: 0 on success, non-zero error code on failure.
+ */
+int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val)
+{
+	int ret;
+	struct intel_guc *guc = slpc_to_guc(slpc);
+	struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
+	intel_wakeref_t wakeref;
+
+	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
+
+	ret = slpc_set_param(slpc,
+		       SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
+		       val);
+	if (ret) {
+		drm_err(&i915->drm,
+			"Set min frequency for unslice returned %d", ret);
+		ret = -EIO;
+		goto done;
+	}
+
+done:
+	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
+	return ret;
+}
+
 /*
  * intel_guc_slpc_enable() - Start SLPC
  * @slpc: pointer to intel_guc_slpc.
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
index a2643b904165..a473e1ea7c10 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
@@ -34,5 +34,7 @@ struct intel_guc_slpc {
 int intel_guc_slpc_init(struct intel_guc_slpc *slpc);
 int intel_guc_slpc_enable(struct intel_guc_slpc *slpc);
 void intel_guc_slpc_fini(struct intel_guc_slpc *slpc);
+int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val);
+int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val);
 
 #endif
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 09/16] drm/i915/guc/slpc: Add get max/min freq hooks
  2021-07-10  1:20 [PATCH 00/16] Enable GuC based power management features Vinay Belgaumkar
                   ` (6 preceding siblings ...)
  2021-07-10  1:20 ` [PATCH 08/16] drm/i915/guc/slpc: Add methods to set min/max frequency Vinay Belgaumkar
@ 2021-07-10  1:20 ` Vinay Belgaumkar
  2021-07-10 17:52   ` Michal Wajdeczko
  2021-07-10  1:20 ` [PATCH 10/16] drm/i915/guc/slpc: Add debugfs for slpc info Vinay Belgaumkar
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 49+ messages in thread
From: Vinay Belgaumkar @ 2021-07-10  1:20 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Vinay Belgaumkar, Sundaresan Sujaritha

Add helpers to read the min/max frequency being used
by SLPC. This is done by send a h2g command which forces
SLPC to update the shared data struct which can then be
read.

Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
---
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 58 +++++++++++++++++++++
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h |  2 +
 2 files changed, 60 insertions(+)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
index 19cb26479942..98a283d31734 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -278,6 +278,35 @@ int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val)
 	return ret;
 }
 
+int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val)
+{
+	struct slpc_shared_data *data;
+	intel_wakeref_t wakeref;
+	struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915;
+	int ret = 0;
+
+	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
+
+	/* Force GuC to update task data */
+	if (slpc_read_task_state(slpc)) {
+		DRM_ERROR("Unable to update task data");
+		ret = -EIO;
+		goto done;
+	}
+
+	GEM_BUG_ON(!slpc->vma);
+
+	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));
+	data = slpc->vaddr;
+
+	*val = DIV_ROUND_CLOSEST(data->task_state_data.max_unslice_freq *
+				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER);
+
+done:
+	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
+	return ret;
+}
+
 /**
  * intel_guc_slpc_min_freq_set() - Set min frequency limit for SLPC.
  * @slpc: pointer to intel_guc_slpc.
@@ -312,6 +341,35 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val)
 	return ret;
 }
 
+int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val)
+{
+	struct slpc_shared_data *data;
+	intel_wakeref_t wakeref;
+	struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915;
+	int ret = 0;
+
+	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
+
+	/* Force GuC to update task data */
+	if (slpc_read_task_state(slpc)) {
+		DRM_ERROR("Unable to update task data");
+		ret = -EIO;
+		goto done;
+	}
+
+	GEM_BUG_ON(!slpc->vma);
+
+	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));
+	data = slpc->vaddr;
+
+	*val = DIV_ROUND_CLOSEST(data->task_state_data.min_unslice_freq *
+				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER);
+
+done:
+	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
+	return ret;
+}
+
 /*
  * intel_guc_slpc_enable() - Start SLPC
  * @slpc: pointer to intel_guc_slpc.
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
index a473e1ea7c10..2cb830cdacb5 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
@@ -36,5 +36,7 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc);
 void intel_guc_slpc_fini(struct intel_guc_slpc *slpc);
 int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val);
 int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val);
+int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val);
+int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val);
 
 #endif
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 10/16] drm/i915/guc/slpc: Add debugfs for slpc info
  2021-07-10  1:20 [PATCH 00/16] Enable GuC based power management features Vinay Belgaumkar
                   ` (7 preceding siblings ...)
  2021-07-10  1:20 ` [PATCH 09/16] drm/i915/guc/slpc: Add get max/min freq hooks Vinay Belgaumkar
@ 2021-07-10  1:20 ` Vinay Belgaumkar
  2021-07-10 18:08   ` Michal Wajdeczko
  2021-07-10  1:20 ` [PATCH 11/16] drm/i915/guc/slpc: Enable ARAT timer interrupt Vinay Belgaumkar
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 49+ messages in thread
From: Vinay Belgaumkar @ 2021-07-10  1:20 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Vinay Belgaumkar, Sundaresan Sujaritha

This prints out relevant SLPC info from the SLPC shared structure.

We will send a h2g message which forces SLPC to update the
shared data structure with latest information before reading it.

Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
---
 .../gpu/drm/i915/gt/uc/intel_guc_debugfs.c    | 16 ++++++
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c   | 53 +++++++++++++++++++
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h   |  3 ++
 3 files changed, 72 insertions(+)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
index 9a03ff56e654..bef749e54601 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
@@ -12,6 +12,7 @@
 #include "gt/uc/intel_guc_ct.h"
 #include "gt/uc/intel_guc_ads.h"
 #include "gt/uc/intel_guc_submission.h"
+#include "gt/uc/intel_guc_slpc.h"
 
 static int guc_info_show(struct seq_file *m, void *data)
 {
@@ -50,11 +51,26 @@ static int guc_registered_contexts_show(struct seq_file *m, void *data)
 }
 DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_registered_contexts);
 
+static int guc_slpc_info_show(struct seq_file *m, void *unused)
+{
+	struct intel_guc *guc = m->private;
+	struct intel_guc_slpc *slpc = &guc->slpc;
+	struct drm_printer p = drm_seq_file_printer(m);
+
+	if (!intel_guc_slpc_is_used(guc))
+		return -ENODEV;
+
+	return intel_guc_slpc_info(slpc, &p);
+}
+
+DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_slpc_info);
+
 void intel_guc_debugfs_register(struct intel_guc *guc, struct dentry *root)
 {
 	static const struct debugfs_gt_file files[] = {
 		{ "guc_info", &guc_info_fops, NULL },
 		{ "guc_registered_contexts", &guc_registered_contexts_fops, NULL },
+		{ "guc_slpc_info", &guc_slpc_info_fops, NULL},
 	};
 
 	if (!intel_guc_is_supported(guc))
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
index 98a283d31734..d179ba14ece6 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -432,6 +432,59 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
 	return 0;
 }
 
+int intel_guc_slpc_info(struct intel_guc_slpc *slpc, struct drm_printer *p)
+{
+	struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915;
+	struct slpc_shared_data *data;
+	struct slpc_platform_info *platform_info;
+	struct slpc_task_state_data *task_state_data;
+	intel_wakeref_t wakeref;
+	int ret = 0;
+
+	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
+
+	if (slpc_read_task_state(slpc)) {
+		ret = -EIO;
+		goto done;
+	}
+
+	GEM_BUG_ON(!slpc->vma);
+
+	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));
+	data = slpc->vaddr;
+
+	platform_info = &data->platform_info;
+	task_state_data = &data->task_state_data;
+
+	drm_printf(p, "SLPC state: %s\n", slpc_state_stringify(data->global_state));
+	drm_printf(p, "\tgtperf task active: %d\n",
+			task_state_data->gtperf_task_active);
+	drm_printf(p, "\tdcc task active: %d\n",
+				task_state_data->dcc_task_active);
+	drm_printf(p, "\tin dcc: %d\n",
+				task_state_data->in_dcc);
+	drm_printf(p, "\tfreq switch active: %d\n",
+				task_state_data->freq_switch_active);
+	drm_printf(p, "\tibc enabled: %d\n",
+				task_state_data->ibc_enabled);
+	drm_printf(p, "\tibc active: %d\n",
+				task_state_data->ibc_active);
+	drm_printf(p, "\tpg1 enabled: %s\n",
+				yesno(task_state_data->pg1_enabled));
+	drm_printf(p, "\tpg1 active: %s\n",
+				yesno(task_state_data->pg1_active));
+	drm_printf(p, "\tmax freq: %dMHz\n",
+				DIV_ROUND_CLOSEST(data->task_state_data.max_unslice_freq *
+				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER));
+	drm_printf(p, "\tmin freq: %dMHz\n",
+				DIV_ROUND_CLOSEST(data->task_state_data.min_unslice_freq *
+				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER));
+
+done:
+	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
+	return ret;
+}
+
 void intel_guc_slpc_fini(struct intel_guc_slpc *slpc)
 {
 	if (!slpc->vma)
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
index 2cb830cdacb5..cd12c5f19f4b 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
@@ -10,6 +10,8 @@
 #include <linux/mutex.h>
 #include "intel_guc_slpc_fwif.h"
 
+struct drm_printer;
+
 struct intel_guc_slpc {
 	/*Protects access to vma and SLPC actions */
 	struct i915_vma *vma;
@@ -38,5 +40,6 @@ int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val);
 int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val);
 int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val);
 int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val);
+int intel_guc_slpc_info(struct intel_guc_slpc *slpc, struct drm_printer *p);
 
 #endif
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 11/16] drm/i915/guc/slpc: Enable ARAT timer interrupt
  2021-07-10  1:20 [PATCH 00/16] Enable GuC based power management features Vinay Belgaumkar
                   ` (8 preceding siblings ...)
  2021-07-10  1:20 ` [PATCH 10/16] drm/i915/guc/slpc: Add debugfs for slpc info Vinay Belgaumkar
@ 2021-07-10  1:20 ` Vinay Belgaumkar
  2021-07-10  1:20 ` [PATCH 12/16] drm/i915/guc/slpc: Cache platform frequency limits for slpc Vinay Belgaumkar
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 49+ messages in thread
From: Vinay Belgaumkar @ 2021-07-10  1:20 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Vinay Belgaumkar

This interrupt is enabled during RPS initialization, and
now needs to be done by slpc code. It allows ARAT timer
expiry interrupts to get forwarded to GuC.

Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
---
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 16 ++++++++++++++++
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h |  2 ++
 drivers/gpu/drm/i915/gt/uc/intel_uc.c       |  8 ++++++++
 3 files changed, 26 insertions(+)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
index d179ba14ece6..d32274cd1db7 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -370,6 +370,20 @@ int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val)
 	return ret;
 }
 
+void intel_guc_pm_intrmsk_enable(struct intel_gt *gt)
+{
+	u32 pm_intrmsk_mbz = 0;
+
+	/* Allow GuC to receive ARAT timer expiry event.
+	 * This interrupt register is setup by RPS code
+	 * when host based Turbo is enabled.
+	 */
+	pm_intrmsk_mbz |= ARAT_EXPIRED_INTRMSK;
+
+	intel_uncore_rmw(gt->uncore,
+			   GEN6_PMINTRMSK, pm_intrmsk_mbz, 0);
+}
+
 /*
  * intel_guc_slpc_enable() - Start SLPC
  * @slpc: pointer to intel_guc_slpc.
@@ -417,6 +431,8 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
 
 	DRM_INFO("SLPC state: %s\n", get_slpc_state(slpc));
 
+	intel_guc_pm_intrmsk_enable(&i915->gt);
+
 	if (slpc_read_task_state(slpc))
 		drm_err(&i915->drm, "Unable to read task state data");
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
index cd12c5f19f4b..2af0c5eb8c9a 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
@@ -10,6 +10,7 @@
 #include <linux/mutex.h>
 #include "intel_guc_slpc_fwif.h"
 
+struct intel_gt;
 struct drm_printer;
 
 struct intel_guc_slpc {
@@ -41,5 +42,6 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val);
 int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val);
 int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val);
 int intel_guc_slpc_info(struct intel_guc_slpc *slpc, struct drm_printer *p);
+void intel_guc_pm_intrmsk_enable(struct intel_gt *gt);
 
 #endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
index 7b6c767d3eb0..823f8d3d8df7 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
@@ -655,6 +655,7 @@ void intel_uc_suspend(struct intel_uc *uc)
 static int __uc_resume(struct intel_uc *uc, bool enable_communication)
 {
 	struct intel_guc *guc = &uc->guc;
+	struct intel_gt *gt = guc_to_gt(guc);
 	int err;
 
 	if (!intel_guc_is_fw_running(guc))
@@ -666,6 +667,13 @@ static int __uc_resume(struct intel_uc *uc, bool enable_communication)
 	if (enable_communication)
 		guc_enable_communication(guc);
 
+	/* If we are only resuming GuC communication but not reloading
+	 * GuC, we need to ensure the ARAT timer interrupt is enabled
+	 * again. In case of GuC reload, it is enabled during slpc enable.
+	 */
+	if (enable_communication && intel_uc_uses_guc_slpc(uc))
+		intel_guc_pm_intrmsk_enable(gt);
+
 	err = intel_guc_resume(guc);
 	if (err) {
 		DRM_DEBUG_DRIVER("Failed to resume GuC, err=%d", err);
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 12/16] drm/i915/guc/slpc: Cache platform frequency limits for slpc
  2021-07-10  1:20 [PATCH 00/16] Enable GuC based power management features Vinay Belgaumkar
                   ` (9 preceding siblings ...)
  2021-07-10  1:20 ` [PATCH 11/16] drm/i915/guc/slpc: Enable ARAT timer interrupt Vinay Belgaumkar
@ 2021-07-10  1:20 ` Vinay Belgaumkar
  2021-07-10 18:15   ` [Intel-gfx] " Michal Wajdeczko
  2021-07-10  1:20 ` [PATCH 13/16] drm/i915/guc/slpc: Update slpc to use platform min/max Vinay Belgaumkar
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 49+ messages in thread
From: Vinay Belgaumkar @ 2021-07-10  1:20 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Vinay Belgaumkar

Cache rp0, rp1 and rpn platform limits into slpc structure
for range checking while setting min/max frequencies.

Also add "soft" limits which keep track of frequency changes
made from userland. These are initially set to platform min
and max.

Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
---
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 41 +++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
index d32274cd1db7..6e978f27b7a6 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -86,6 +86,9 @@ static int slpc_shared_data_init(struct intel_guc_slpc *slpc)
 		return err;
 	}
 
+	slpc->max_freq_softlimit = 0;
+	slpc->min_freq_softlimit = 0;
+
 	return err;
 }
 
@@ -384,6 +387,29 @@ void intel_guc_pm_intrmsk_enable(struct intel_gt *gt)
 			   GEN6_PMINTRMSK, pm_intrmsk_mbz, 0);
 }
 
+static int intel_guc_slpc_set_softlimits(struct intel_guc_slpc *slpc)
+{
+	int ret = 0;
+
+	/* Softlimits are initially equivalent to platform limits
+	 * unless they have deviated from defaults, in which case,
+	 * we retain the values and set min/max accordingly.
+	 */
+	if (!slpc->max_freq_softlimit)
+		slpc->max_freq_softlimit = slpc->rp0_freq;
+	else if (slpc->max_freq_softlimit != slpc->rp0_freq)
+		ret = intel_guc_slpc_set_max_freq(slpc,
+					slpc->max_freq_softlimit);
+
+	if (!slpc->min_freq_softlimit)
+		slpc->min_freq_softlimit = slpc->min_freq;
+	else if (slpc->min_freq_softlimit != slpc->min_freq)
+		ret = intel_guc_slpc_set_min_freq(slpc,
+					slpc->min_freq_softlimit);
+
+	return ret;
+}
+
 /*
  * intel_guc_slpc_enable() - Start SLPC
  * @slpc: pointer to intel_guc_slpc.
@@ -402,6 +428,7 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
 	struct drm_i915_private *i915 = slpc_to_i915(slpc);
 	struct slpc_shared_data *data;
 	int ret;
+	u32 rp_state_cap;
 
 	GEM_BUG_ON(!slpc->vma);
 
@@ -445,6 +472,20 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
 			DIV_ROUND_CLOSEST(data->task_state_data.max_unslice_freq *
 				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER));
 
+	rp_state_cap = intel_uncore_read(i915->gt.uncore, GEN6_RP_STATE_CAP);
+
+	slpc->rp0_freq = ((rp_state_cap >> 0) & 0xff) * GT_FREQUENCY_MULTIPLIER;
+	slpc->min_freq = ((rp_state_cap >> 16) & 0xff) * GT_FREQUENCY_MULTIPLIER;
+	slpc->rp1_freq = ((rp_state_cap >> 8) & 0xff) * GT_FREQUENCY_MULTIPLIER;
+
+	if (intel_guc_slpc_set_softlimits(slpc))
+		drm_err(&i915->drm, "Unable to set softlimits");
+
+	drm_info(&i915->drm,
+		 "Platform fused frequency values -  min: %u Mhz, max: %u Mhz",
+		 slpc->min_freq,
+		 slpc->rp0_freq);
+
 	return 0;
 }
 
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 13/16] drm/i915/guc/slpc: Update slpc to use platform min/max
  2021-07-10  1:20 [PATCH 00/16] Enable GuC based power management features Vinay Belgaumkar
                   ` (10 preceding siblings ...)
  2021-07-10  1:20 ` [PATCH 12/16] drm/i915/guc/slpc: Cache platform frequency limits for slpc Vinay Belgaumkar
@ 2021-07-10  1:20 ` Vinay Belgaumkar
  2021-07-10  1:20 ` [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc Vinay Belgaumkar
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 49+ messages in thread
From: Vinay Belgaumkar @ 2021-07-10  1:20 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Vinay Belgaumkar

SLPC requests efficient frequency by default instead of min.
It provides a flag to turn this off. Set that flag to maintain
original semantics so that tests do not fail. SLPC can also
request frequency that is much higher than the platform max,
update that as well for the same reason.

Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
---
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 55 +++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
index 6e978f27b7a6..db575443ffb2 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -109,6 +109,17 @@ static int slpc_send(struct intel_guc_slpc *slpc,
 	return intel_guc_send(guc, action, in_len);
 }
 
+static int host2guc_slpc_unset_param(struct intel_guc_slpc *slpc,
+				   u32 id)
+{
+	struct slpc_event_input data = {0};
+
+	data.header.value = SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 1);
+	data.args[0] = id;
+
+	return slpc_send(slpc, &data, 4);
+}
+
 static int host2guc_slpc_set_param(struct intel_guc_slpc *slpc,
 				   u32 id, u32 value)
 {
@@ -150,6 +161,20 @@ static int host2guc_slpc_query_task_state(struct intel_guc_slpc *slpc)
 	return slpc_send(slpc, &data, 4);
 }
 
+static int slpc_unset_param(struct intel_guc_slpc *slpc, u32 id)
+{
+	struct drm_i915_private *i915 = slpc_to_i915(slpc);
+
+	GEM_BUG_ON(id >= SLPC_MAX_PARAM);
+
+	if (host2guc_slpc_unset_param(slpc, id)) {
+		drm_err(&i915->drm, "Unable to unset param %x", id);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static int slpc_set_param(struct intel_guc_slpc *slpc, u32 id, u32 value)
 {
 	struct drm_i915_private *i915 = slpc_to_i915(slpc);
@@ -410,6 +435,32 @@ static int intel_guc_slpc_set_softlimits(struct intel_guc_slpc *slpc)
 	return ret;
 }
 
+static void intel_guc_slpc_ignore_eff_freq(struct intel_guc_slpc *slpc, bool ignore)
+{
+	if (ignore) {
+		/* A failure here does not affect the algorithm in a fatal way */
+		slpc_set_param(slpc,
+		   SLPC_IGNORE_EFFICIENT_FREQUENCY,
+		   ignore);
+		slpc_set_param(slpc,
+		   SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
+		   slpc->min_freq);
+	} else {
+		slpc_unset_param(slpc,
+		   SLPC_IGNORE_EFFICIENT_FREQUENCY);
+		slpc_unset_param(slpc,
+		   SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ);
+	}
+}
+
+static void intel_guc_slpc_use_fused_rp0(struct intel_guc_slpc *slpc)
+{
+	/* Force slpc to used platform rp0 */
+	slpc_set_param(slpc,
+	   SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ,
+	   slpc->rp0_freq);
+}
+
 /*
  * intel_guc_slpc_enable() - Start SLPC
  * @slpc: pointer to intel_guc_slpc.
@@ -478,6 +529,10 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
 	slpc->min_freq = ((rp_state_cap >> 16) & 0xff) * GT_FREQUENCY_MULTIPLIER;
 	slpc->rp1_freq = ((rp_state_cap >> 8) & 0xff) * GT_FREQUENCY_MULTIPLIER;
 
+	/* Ignore efficient freq and set min/max to platform min/max */
+	intel_guc_slpc_ignore_eff_freq(slpc, true);
+	intel_guc_slpc_use_fused_rp0(slpc);
+
 	if (intel_guc_slpc_set_softlimits(slpc))
 		drm_err(&i915->drm, "Unable to set softlimits");
 
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc
  2021-07-10  1:20 [PATCH 00/16] Enable GuC based power management features Vinay Belgaumkar
                   ` (11 preceding siblings ...)
  2021-07-10  1:20 ` [PATCH 13/16] drm/i915/guc/slpc: Update slpc to use platform min/max Vinay Belgaumkar
@ 2021-07-10  1:20 ` Vinay Belgaumkar
  2021-07-10  6:18   ` kernel test robot
                     ` (4 more replies)
  2021-07-10  1:20 ` [PATCH 15/16] drm/i915/guc/slpc: slpc selftest Vinay Belgaumkar
  2021-07-10  1:20 ` [PATCH 16/16] drm/i915/guc/rc: Setup and enable GUCRC feature Vinay Belgaumkar
  14 siblings, 5 replies; 49+ messages in thread
From: Vinay Belgaumkar @ 2021-07-10  1:20 UTC (permalink / raw)
  To: intel-gfx, dri-devel
  Cc: Vinay Belgaumkar, Sujaritha Sundaresan, Tvrtko Ursulin

Update the get/set min/max freq hooks to work for
slpc case as well. Consolidate helpers for requested/min/max
frequency get/set to intel_rps where the proper action can
be taken depending on whether slpc is enabled.

Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Signed-off-by: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
---
 drivers/gpu/drm/i915/gt/intel_rps.c | 135 ++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gt/intel_rps.h |   5 ++
 drivers/gpu/drm/i915/i915_pmu.c     |   2 +-
 drivers/gpu/drm/i915/i915_reg.h     |   2 +
 drivers/gpu/drm/i915/i915_sysfs.c   |  71 +++------------
 5 files changed, 154 insertions(+), 61 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c
index e858eeb2c59d..88ffc5d90730 100644
--- a/drivers/gpu/drm/i915/gt/intel_rps.c
+++ b/drivers/gpu/drm/i915/gt/intel_rps.c
@@ -37,6 +37,12 @@ static struct intel_uncore *rps_to_uncore(struct intel_rps *rps)
 	return rps_to_gt(rps)->uncore;
 }
 
+static struct intel_guc_slpc *rps_to_slpc(struct intel_rps *rps)
+{
+	struct intel_gt *gt = rps_to_gt(rps);
+	return &gt->uc.guc.slpc;
+}
+
 static bool rps_uses_slpc(struct intel_rps *rps)
 {
 	struct intel_gt *gt = rps_to_gt(rps);
@@ -1960,6 +1966,135 @@ u32 intel_rps_read_actual_frequency(struct intel_rps *rps)
 	return freq;
 }
 
+u32 intel_rps_read_punit_req(struct intel_rps *rps)
+{
+	struct intel_uncore *uncore = rps_to_uncore(rps);
+
+	u32 pureq = intel_uncore_read(uncore, GEN6_RPNSWREQ);
+
+	return pureq;
+}
+
+u32 intel_rps_get_req(struct intel_rps *rps, u32 pureq)
+{
+	u32 req = pureq >> GEN9_SW_REQ_UNSLICE_RATIO_SHIFT;
+
+	return req;
+}
+
+u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps)
+{
+	u32 freq = intel_rps_get_req(rps, intel_rps_read_punit_req(rps));
+
+	return intel_gpu_freq(rps, freq);
+}
+
+u32 intel_rps_get_requested_frequency(struct intel_rps *rps)
+{
+	if (rps_uses_slpc(rps))
+		return intel_rps_read_punit_req_frequency(rps);
+	else
+		return intel_gpu_freq(rps, rps->cur_freq);
+}
+
+u32 intel_rps_get_max_frequency(struct intel_rps *rps)
+{
+	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
+
+	if (rps_uses_slpc(rps))
+		return slpc->max_freq_softlimit;
+	else
+		return intel_gpu_freq(rps, rps->max_freq_softlimit);
+}
+
+int intel_rps_set_max_frequency(struct intel_rps *rps, u32 val)
+{
+	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
+	int ret;
+
+	if (rps_uses_slpc(rps))
+		return intel_guc_slpc_set_max_freq(slpc, val);
+
+	mutex_lock(&rps->lock);
+
+	val = intel_freq_opcode(rps, val);
+	if (val < rps->min_freq ||
+	    val > rps->max_freq ||
+	    val < rps->min_freq_softlimit) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	if (val > rps->rp0_freq)
+		DRM_DEBUG("User requested overclocking to %d\n",
+			  intel_gpu_freq(rps, val));
+
+	rps->max_freq_softlimit = val;
+
+	val = clamp_t(int, rps->cur_freq,
+		      rps->min_freq_softlimit,
+		      rps->max_freq_softlimit);
+
+	/*
+	 * We still need *_set_rps to process the new max_delay and
+	 * update the interrupt limits and PMINTRMSK even though
+	 * frequency request may be unchanged.
+	 */
+	intel_rps_set(rps, val);
+
+unlock:
+	mutex_unlock(&rps->lock);
+
+	return ret;
+}
+
+u32 intel_rps_get_min_frequency(struct intel_rps *rps)
+{
+	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
+
+	if (rps_uses_slpc(rps))
+		return slpc->min_freq_softlimit;
+	else
+		return intel_gpu_freq(rps, rps->min_freq_softlimit);
+}
+
+int intel_rps_set_min_frequency(struct intel_rps *rps, u32 val)
+{
+	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
+	int ret;
+
+	if (rps_uses_slpc(rps))
+		return intel_guc_slpc_set_min_freq(slpc, val);
+
+	mutex_lock(&rps->lock);
+
+	val = intel_freq_opcode(rps, val);
+	if (val < rps->min_freq ||
+	    val > rps->max_freq ||
+	    val > rps->max_freq_softlimit) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	rps->min_freq_softlimit = val;
+
+	val = clamp_t(int, rps->cur_freq,
+		      rps->min_freq_softlimit,
+		      rps->max_freq_softlimit);
+
+	/*
+	 * We still need *_set_rps to process the new min_delay and
+	 * update the interrupt limits and PMINTRMSK even though
+	 * frequency request may be unchanged.
+	 */
+	intel_rps_set(rps, val);
+
+unlock:
+	mutex_unlock(&rps->lock);
+
+	return ret;
+}
+
 /* External interface for intel_ips.ko */
 
 static struct drm_i915_private __rcu *ips_mchdev;
diff --git a/drivers/gpu/drm/i915/gt/intel_rps.h b/drivers/gpu/drm/i915/gt/intel_rps.h
index 1d2cfc98b510..9a09ff5ebf64 100644
--- a/drivers/gpu/drm/i915/gt/intel_rps.h
+++ b/drivers/gpu/drm/i915/gt/intel_rps.h
@@ -31,6 +31,11 @@ int intel_gpu_freq(struct intel_rps *rps, int val);
 int intel_freq_opcode(struct intel_rps *rps, int val);
 u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat1);
 u32 intel_rps_read_actual_frequency(struct intel_rps *rps);
+u32 intel_rps_get_requested_frequency(struct intel_rps *rps);
+u32 intel_rps_get_min_frequency(struct intel_rps *rps);
+int intel_rps_set_min_frequency(struct intel_rps *rps, u32 val);
+u32 intel_rps_get_max_frequency(struct intel_rps *rps);
+int intel_rps_set_max_frequency(struct intel_rps *rps, u32 val);
 
 void gen5_rps_irq_handler(struct intel_rps *rps);
 void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir);
diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c
index 34d37d46a126..a896bec18255 100644
--- a/drivers/gpu/drm/i915/i915_pmu.c
+++ b/drivers/gpu/drm/i915/i915_pmu.c
@@ -407,7 +407,7 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns)
 
 	if (pmu->enable & config_mask(I915_PMU_REQUESTED_FREQUENCY)) {
 		add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_REQ],
-				intel_gpu_freq(rps, rps->cur_freq),
+				intel_rps_get_requested_frequency(rps),
 				period_ns / 1000);
 	}
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 7d9e90aa3ec0..8ab3c2f8f8e4 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -9195,6 +9195,8 @@ enum {
 #define   GEN9_FREQUENCY(x)			((x) << 23)
 #define   GEN6_OFFSET(x)			((x) << 19)
 #define   GEN6_AGGRESSIVE_TURBO			(0 << 15)
+#define   GEN9_SW_REQ_UNSLICE_RATIO_SHIFT 	23
+
 #define GEN6_RC_VIDEO_FREQ			_MMIO(0xA00C)
 #define GEN6_RC_CONTROL				_MMIO(0xA090)
 #define   GEN6_RC_CTL_RC6pp_ENABLE		(1 << 16)
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 873bf996ceb5..f2eee8491b19 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -272,7 +272,7 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
 	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
 	struct intel_rps *rps = &i915->gt.rps;
 
-	return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->cur_freq));
+	return sysfs_emit(buf, "%d\n", intel_rps_get_requested_frequency(rps));
 }
 
 static ssize_t gt_boost_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
@@ -326,9 +326,10 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev,
 static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
 {
 	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	struct intel_rps *rps = &dev_priv->gt.rps;
+	struct intel_gt *gt = &dev_priv->gt;
+	struct intel_rps *rps = &gt->rps;
 
-	return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->max_freq_softlimit));
+	return sysfs_emit(buf, "%d\n", intel_rps_get_max_frequency(rps));
 }
 
 static ssize_t gt_max_freq_mhz_store(struct device *kdev,
@@ -336,7 +337,8 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 				     const char *buf, size_t count)
 {
 	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	struct intel_rps *rps = &dev_priv->gt.rps;
+	struct intel_gt *gt = &dev_priv->gt;
+	struct intel_rps *rps = &gt->rps;
 	ssize_t ret;
 	u32 val;
 
@@ -344,35 +346,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 	if (ret)
 		return ret;
 
-	mutex_lock(&rps->lock);
-
-	val = intel_freq_opcode(rps, val);
-	if (val < rps->min_freq ||
-	    val > rps->max_freq ||
-	    val < rps->min_freq_softlimit) {
-		ret = -EINVAL;
-		goto unlock;
-	}
-
-	if (val > rps->rp0_freq)
-		DRM_DEBUG("User requested overclocking to %d\n",
-			  intel_gpu_freq(rps, val));
-
-	rps->max_freq_softlimit = val;
-
-	val = clamp_t(int, rps->cur_freq,
-		      rps->min_freq_softlimit,
-		      rps->max_freq_softlimit);
-
-	/*
-	 * We still need *_set_rps to process the new max_delay and
-	 * update the interrupt limits and PMINTRMSK even though
-	 * frequency request may be unchanged.
-	 */
-	intel_rps_set(rps, val);
-
-unlock:
-	mutex_unlock(&rps->lock);
+	ret = intel_rps_set_max_frequency(rps, val);
 
 	return ret ?: count;
 }
@@ -380,9 +354,10 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
 {
 	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	struct intel_rps *rps = &dev_priv->gt.rps;
+	struct intel_gt *gt = &dev_priv->gt;
+	struct intel_rps *rps = &gt->rps;
 
-	return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->min_freq_softlimit));
+	return sysfs_emit(buf, "%d\n", intel_rps_get_min_frequency(rps));
 }
 
 static ssize_t gt_min_freq_mhz_store(struct device *kdev,
@@ -398,31 +373,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 	if (ret)
 		return ret;
 
-	mutex_lock(&rps->lock);
-
-	val = intel_freq_opcode(rps, val);
-	if (val < rps->min_freq ||
-	    val > rps->max_freq ||
-	    val > rps->max_freq_softlimit) {
-		ret = -EINVAL;
-		goto unlock;
-	}
-
-	rps->min_freq_softlimit = val;
-
-	val = clamp_t(int, rps->cur_freq,
-		      rps->min_freq_softlimit,
-		      rps->max_freq_softlimit);
-
-	/*
-	 * We still need *_set_rps to process the new min_delay and
-	 * update the interrupt limits and PMINTRMSK even though
-	 * frequency request may be unchanged.
-	 */
-	intel_rps_set(rps, val);
-
-unlock:
-	mutex_unlock(&rps->lock);
+	ret = intel_rps_set_min_frequency(rps, val);
 
 	return ret ?: count;
 }
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 15/16] drm/i915/guc/slpc: slpc selftest
  2021-07-10  1:20 [PATCH 00/16] Enable GuC based power management features Vinay Belgaumkar
                   ` (12 preceding siblings ...)
  2021-07-10  1:20 ` [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc Vinay Belgaumkar
@ 2021-07-10  1:20 ` Vinay Belgaumkar
  2021-07-10 18:29   ` Michal Wajdeczko
  2021-07-10  1:20 ` [PATCH 16/16] drm/i915/guc/rc: Setup and enable GUCRC feature Vinay Belgaumkar
  14 siblings, 1 reply; 49+ messages in thread
From: Vinay Belgaumkar @ 2021-07-10  1:20 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Vinay Belgaumkar

Tests that exercise the slpc get/set frequency interfaces.

Clamp_max will set max frequency to multiple levels and check
that slpc requests frequency lower than or equal to it.

Clamp_min will set min frequency to different levels and check
if slpc requests are higher or equal to those levels.

Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
---
 drivers/gpu/drm/i915/gt/intel_rps.c           |   1 +
 drivers/gpu/drm/i915/gt/selftest_slpc.c       | 333 ++++++++++++++++++
 drivers/gpu/drm/i915/gt/selftest_slpc.h       |  12 +
 .../drm/i915/selftests/i915_live_selftests.h  |   1 +
 4 files changed, 347 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/gt/selftest_slpc.c
 create mode 100644 drivers/gpu/drm/i915/gt/selftest_slpc.h

diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c
index 88ffc5d90730..16ac2e840881 100644
--- a/drivers/gpu/drm/i915/gt/intel_rps.c
+++ b/drivers/gpu/drm/i915/gt/intel_rps.c
@@ -2288,4 +2288,5 @@ EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
 
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftest_rps.c"
+#include "selftest_slpc.c"
 #endif
diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c b/drivers/gpu/drm/i915/gt/selftest_slpc.c
new file mode 100644
index 000000000000..f440c1cb2afa
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+#include "selftest_slpc.h"
+#include "selftest_rps.h"
+
+#include <linux/pm_qos.h>
+#include <linux/sort.h>
+
+#include "intel_engine_heartbeat.h"
+#include "intel_engine_pm.h"
+#include "intel_gpu_commands.h"
+#include "intel_gt_clock_utils.h"
+#include "intel_gt_pm.h"
+#include "intel_rc6.h"
+#include "selftest_engine_heartbeat.h"
+#include "intel_rps.h"
+#include "selftests/igt_flush_test.h"
+#include "selftests/igt_spinner.h"
+
+#define NUM_STEPS 5
+#define H2G_DELAY 50000
+#define delay_for_h2g() usleep_range(H2G_DELAY, H2G_DELAY + 10000)
+
+static int set_min_freq(struct intel_guc_slpc *slpc, int freq)
+{
+	int ret;
+	ret = intel_guc_slpc_set_min_freq(slpc, freq);
+	if (ret) {
+		pr_err("Could not set min frequency to [%d]\n", freq);
+		return ret;
+	} else {
+		/* Delay to ensure h2g completes */
+		delay_for_h2g();
+	}
+
+	return ret;
+}
+
+static int set_max_freq(struct intel_guc_slpc *slpc, int freq)
+{
+	int ret;
+	ret = intel_guc_slpc_set_max_freq(slpc, freq);
+	if (ret) {
+		pr_err("Could not set maximum frequency [%d]\n",
+			freq);
+		return ret;
+	} else {
+		/* Delay to ensure h2g completes */
+		delay_for_h2g();
+	}
+
+	return ret;
+}
+
+int live_slpc_clamp_min(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct intel_gt *gt = &i915->gt;
+	struct intel_guc_slpc *slpc;
+	struct intel_rps *rps;
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+	struct igt_spinner spin;
+	int err = 0;
+	u32 slpc_min_freq, slpc_max_freq;
+
+
+	slpc = &gt->uc.guc.slpc;
+	rps = &gt->rps;
+
+	if (!intel_uc_uses_guc_slpc(&gt->uc))
+		return 0;
+
+	if (igt_spinner_init(&spin, gt))
+		return -ENOMEM;
+
+	if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) {
+		pr_err("Could not get SLPC max freq");
+		return -EIO;
+	}
+
+	if (intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq)) {
+		pr_err("Could not get SLPC min freq");
+		return -EIO;
+	}
+
+	if (slpc_min_freq == slpc_max_freq) {
+		pr_err("Min/Max are fused to the same value");
+		return -EINVAL;
+	}
+
+	intel_gt_pm_wait_for_idle(gt);
+	intel_gt_pm_get(gt);
+	for_each_engine(engine, gt, id) {
+		struct i915_request *rq;
+		u32 step, min_freq, req_freq;
+		u32 act_freq, max_act_freq;
+
+		if (!intel_engine_can_store_dword(engine))
+			continue;
+
+		/* Go from min to max in 5 steps */
+		step = (slpc_max_freq - slpc_min_freq)/NUM_STEPS;
+		max_act_freq = slpc_min_freq;
+		for (min_freq = slpc_min_freq; min_freq < slpc_max_freq; min_freq+=step)
+		{
+			err = set_min_freq(slpc, min_freq);
+			if (err)
+				break;
+
+			st_engine_heartbeat_disable(engine);
+
+
+			rq = igt_spinner_create_request(&spin,
+					engine->kernel_context,
+					MI_NOOP);
+			if (IS_ERR(rq)) {
+				err = PTR_ERR(rq);
+				st_engine_heartbeat_enable(engine);
+				break;
+			}
+
+			i915_request_add(rq);
+
+			if (!igt_wait_for_spinner(&spin, rq)) {
+				pr_err("%s: Spinner did not start\n",
+					engine->name);
+				igt_spinner_end(&spin);
+				st_engine_heartbeat_enable(engine);
+				intel_gt_set_wedged(engine->gt);
+				err = -EIO;
+				break;
+			}
+
+			/* Wait for GuC to detect business and raise
+			 * requested frequency if necessary */
+			delay_for_h2g();
+
+			req_freq = intel_rps_read_punit_req_frequency(rps);
+
+			/* GuC requests freq in multiples of 50/3 MHz */
+			if (req_freq < (min_freq - 50/3)) {
+				pr_err("SWReq is %d, should be at least %d", req_freq,
+					min_freq - 50/3);
+				igt_spinner_end(&spin);
+				st_engine_heartbeat_enable(engine);
+				err = -EINVAL;
+				break;
+			}
+
+			act_freq =  intel_rps_read_actual_frequency(rps);
+			if (act_freq > max_act_freq)
+				max_act_freq = act_freq;
+
+			igt_spinner_end(&spin);
+			st_engine_heartbeat_enable(engine);
+		}
+
+		pr_info("Max actual frequency for %s was %d",
+				engine->name, max_act_freq);
+
+		/* Actual frequency should rise above min */
+		if (max_act_freq == slpc_min_freq) {
+			pr_err("Actual freq did not rise above min");
+			err = -EINVAL;
+		}
+
+		if (err)
+			break;
+	}
+
+	/* Restore min/max frequencies */
+	set_max_freq(slpc, slpc_max_freq);
+	set_min_freq(slpc, slpc_min_freq);
+
+	if (igt_flush_test(gt->i915))
+		err = -EIO;
+
+	intel_gt_pm_put(gt);
+	igt_spinner_fini(&spin);
+	intel_gt_pm_wait_for_idle(gt);
+
+	return err;
+}
+
+int live_slpc_clamp_max(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct intel_gt *gt = &i915->gt;
+	struct intel_guc_slpc *slpc;
+	struct intel_rps *rps;
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+	struct igt_spinner spin;
+	int err = 0;
+	u32 slpc_min_freq, slpc_max_freq;
+
+	slpc = &gt->uc.guc.slpc;
+	rps = &gt->rps;
+
+	if (!intel_uc_uses_guc_slpc(&gt->uc))
+		return 0;
+
+	if (igt_spinner_init(&spin, gt))
+		return -ENOMEM;
+
+	if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) {
+		pr_err("Could not get SLPC max freq");
+		return -EIO;
+	}
+
+	if (intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq)) {
+		pr_err("Could not get SLPC min freq");
+		return -EIO;
+	}
+
+	if (slpc_min_freq == slpc_max_freq) {
+		pr_err("Min/Max are fused to the same value");
+		return -EINVAL;
+	}
+
+	intel_gt_pm_wait_for_idle(gt);
+	intel_gt_pm_get(gt);
+	for_each_engine(engine, gt, id) {
+		struct i915_request *rq;
+		u32 max_freq, req_freq;
+		u32 act_freq, max_act_freq;
+		u32 step;
+
+		if (!intel_engine_can_store_dword(engine))
+			continue;
+
+		/* Go from max to min in 5 steps */
+		step = (slpc_max_freq - slpc_min_freq)/NUM_STEPS;
+		max_act_freq = slpc_min_freq;
+		for (max_freq = slpc_max_freq; max_freq > slpc_min_freq; max_freq-=step)
+		{
+			err = set_max_freq(slpc, max_freq);
+			if (err)
+				break;
+
+			st_engine_heartbeat_disable(engine);
+
+			rq = igt_spinner_create_request(&spin,
+						engine->kernel_context,
+						MI_NOOP);
+			if (IS_ERR(rq)) {
+				st_engine_heartbeat_enable(engine);
+				err = PTR_ERR(rq);
+				break;
+			}
+
+			i915_request_add(rq);
+
+			if (!igt_wait_for_spinner(&spin, rq)) {
+				pr_err("%s: SLPC spinner did not start\n",
+				       engine->name);
+				igt_spinner_end(&spin);
+				st_engine_heartbeat_enable(engine);
+				intel_gt_set_wedged(engine->gt);
+				err = -EIO;
+				break;
+			}
+
+			delay_for_h2g();
+
+			/* Verify that SWREQ indeed was set to specific value */
+			req_freq = intel_rps_read_punit_req_frequency(rps);
+
+			/* GuC requests freq in multiples of 50/3 MHz */
+			if (req_freq > (max_freq + 50/3)) {
+				pr_err("SWReq is %d, should be at most %d", req_freq,
+					max_freq + 50/3);
+				igt_spinner_end(&spin);
+				st_engine_heartbeat_enable(engine);
+				err = -EINVAL;
+				break;
+			}
+
+			act_freq =  intel_rps_read_actual_frequency(rps);
+			if (act_freq > max_act_freq)
+				max_act_freq = act_freq;
+
+			st_engine_heartbeat_enable(engine);
+			igt_spinner_end(&spin);
+
+			if (err)
+				break;
+		}
+
+		pr_info("Max actual frequency for %s was %d",
+				engine->name, max_act_freq);
+
+		/* Actual frequency should rise above min */
+		if (max_act_freq == slpc_min_freq) {
+			pr_err("Actual freq did not rise above min");
+			err = -EINVAL;
+		}
+
+		if (igt_flush_test(gt->i915)) {
+			err = -EIO;
+			break;
+		}
+
+		if (err)
+			break;
+	}
+
+	/* Restore min/max freq */
+	set_max_freq(slpc, slpc_max_freq);
+	set_min_freq(slpc, slpc_min_freq);
+
+	intel_gt_pm_put(gt);
+	igt_spinner_fini(&spin);
+	intel_gt_pm_wait_for_idle(gt);
+
+	return err;
+}
+
+int intel_slpc_live_selftests(struct drm_i915_private *i915)
+{
+	static const struct i915_subtest tests[] = {
+		SUBTEST(live_slpc_clamp_max),
+		SUBTEST(live_slpc_clamp_min),
+	};
+
+	if (intel_gt_is_wedged(&i915->gt))
+		return 0;
+
+	return i915_live_subtests(tests, i915);
+}
diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.h b/drivers/gpu/drm/i915/gt/selftest_slpc.h
new file mode 100644
index 000000000000..8dfb40916a8c
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/selftest_slpc.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#ifndef SELFTEST_SLPC_H
+#define SELFTEST_SLPC_H
+
+int live_slpc_clamp_max(void *arg);
+int live_slpc_clamp_min(void *arg);
+
+#endif /* SELFTEST_SLPC_H */
diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
index e2fd1b61af71..1746a56dda06 100644
--- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
@@ -47,5 +47,6 @@ selftest(hangcheck, intel_hangcheck_live_selftests)
 selftest(execlists, intel_execlists_live_selftests)
 selftest(ring_submission, intel_ring_submission_live_selftests)
 selftest(perf, i915_perf_live_selftests)
+selftest(slpc, intel_slpc_live_selftests)
 /* Here be dragons: keep last to run last! */
 selftest(late_gt_pm, intel_gt_pm_late_selftests)
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 16/16] drm/i915/guc/rc: Setup and enable GUCRC feature
  2021-07-10  1:20 [PATCH 00/16] Enable GuC based power management features Vinay Belgaumkar
                   ` (13 preceding siblings ...)
  2021-07-10  1:20 ` [PATCH 15/16] drm/i915/guc/slpc: slpc selftest Vinay Belgaumkar
@ 2021-07-10  1:20 ` Vinay Belgaumkar
  2021-07-10 18:41   ` [Intel-gfx] " Michal Wajdeczko
  14 siblings, 1 reply; 49+ messages in thread
From: Vinay Belgaumkar @ 2021-07-10  1:20 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Vinay Belgaumkar

This feature hands over the control of HW RC6 to the GUC.
GUC decides when to put HW into RC6 based on it's internal
busyness algorithms.

GUCRC needs GUC submission to be enabled, and only
supported on Gen12+ for now.

When GUCRC is enabled, do not set HW RC6. Use a H2G message
to tell guc to enable GUCRC. When disabling RC6, tell guc to
revert RC6 control back to KMD.

Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
---
 drivers/gpu/drm/i915/Makefile                 |  1 +
 drivers/gpu/drm/i915/gt/intel_rc6.c           | 22 ++++--
 .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h  |  6 ++
 drivers/gpu/drm/i915/gt/uc/intel_guc.c        |  1 +
 drivers/gpu/drm/i915/gt/uc/intel_guc.h        |  2 +
 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c     | 79 +++++++++++++++++++
 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h     | 32 ++++++++
 drivers/gpu/drm/i915/gt/uc/intel_uc.h         |  2 +
 8 files changed, 140 insertions(+), 5 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index d8eac4468df9..3fc17f20d88e 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -186,6 +186,7 @@ i915-y += gt/uc/intel_uc.o \
 	  gt/uc/intel_guc_fw.o \
 	  gt/uc/intel_guc_log.o \
 	  gt/uc/intel_guc_log_debugfs.o \
+	  gt/uc/intel_guc_rc.o \
 	  gt/uc/intel_guc_slpc.o \
 	  gt/uc/intel_guc_submission.o \
 	  gt/uc/intel_huc.o \
diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c
index 259d7eb4e165..299fcf10b04b 100644
--- a/drivers/gpu/drm/i915/gt/intel_rc6.c
+++ b/drivers/gpu/drm/i915/gt/intel_rc6.c
@@ -98,11 +98,19 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6)
 	set(uncore, GEN9_MEDIA_PG_IDLE_HYSTERESIS, 60);
 	set(uncore, GEN9_RENDER_PG_IDLE_HYSTERESIS, 60);
 
-	/* 3a: Enable RC6 */
-	rc6->ctl_enable =
-		GEN6_RC_CTL_HW_ENABLE |
-		GEN6_RC_CTL_RC6_ENABLE |
-		GEN6_RC_CTL_EI_MODE(1);
+	/* 3a: Enable RC6
+	 *
+	 * With GUCRC, we do not enable bit 31 of RC_CTL,
+	 * thus allowing GuC to control RC6 entry/exit fully instead.
+	 * We will not set the HW ENABLE and EI bits
+	 */
+	if (!intel_guc_rc_enable(&gt->uc.guc))
+		rc6->ctl_enable = GEN6_RC_CTL_RC6_ENABLE;
+	else
+		rc6->ctl_enable =
+			GEN6_RC_CTL_HW_ENABLE |
+			GEN6_RC_CTL_RC6_ENABLE |
+			GEN6_RC_CTL_EI_MODE(1);
 
 	pg_enable =
 		GEN9_RENDER_PG_ENABLE |
@@ -513,6 +521,10 @@ static void __intel_rc6_disable(struct intel_rc6 *rc6)
 {
 	struct drm_i915_private *i915 = rc6_to_i915(rc6);
 	struct intel_uncore *uncore = rc6_to_uncore(rc6);
+	struct intel_gt *gt = rc6_to_gt(rc6);
+
+	/* Take control of RC6 back from GuC */
+	intel_guc_rc_disable(&gt->uc.guc);
 
 	intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
 	if (GRAPHICS_VER(i915) >= 9)
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
index 596cf4b818e5..2ddb9cdc0a59 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
@@ -136,6 +136,7 @@ enum intel_guc_action {
 	INTEL_GUC_ACTION_CONTEXT_RESET_NOTIFICATION = 0x1008,
 	INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION = 0x1009,
 	INTEL_GUC_ACTION_SLPC_REQUEST = 0x3003,
+	INTEL_GUC_ACTION_SETUP_PC_GUCRC = 0x3004,
 	INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000,
 	INTEL_GUC_ACTION_REGISTER_CONTEXT = 0x4502,
 	INTEL_GUC_ACTION_DEREGISTER_CONTEXT = 0x4503,
@@ -146,6 +147,11 @@ enum intel_guc_action {
 	INTEL_GUC_ACTION_LIMIT
 };
 
+enum intel_guc_rc_options {
+	INTEL_GUCRC_HOST_CONTROL,
+	INTEL_GUCRC_FIRMWARE_CONTROL,
+};
+
 enum intel_guc_preempt_options {
 	INTEL_GUC_PREEMPT_OPTION_DROP_WORK_Q = 0x4,
 	INTEL_GUC_PREEMPT_OPTION_DROP_SUBMIT_Q = 0x8,
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index 82863a9bc8e8..0d55b24f7c67 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -158,6 +158,7 @@ void intel_guc_init_early(struct intel_guc *guc)
 	intel_guc_log_init_early(&guc->log);
 	intel_guc_submission_init_early(guc);
 	intel_guc_slpc_init_early(guc);
+	intel_guc_rc_init_early(guc);
 
 	mutex_init(&guc->send_mutex);
 	spin_lock_init(&guc->irq_lock);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
index 0dbbd9cf553f..592d52e5e93c 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
@@ -59,6 +59,8 @@ struct intel_guc {
 
 	bool submission_supported;
 	bool submission_selected;
+	bool rc_supported;
+	bool rc_selected;
 	bool slpc_supported;
 	bool slpc_selected;
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
new file mode 100644
index 000000000000..45b61432c56d
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+*/
+
+#include "intel_guc_rc.h"
+#include "gt/intel_gt.h"
+#include "i915_drv.h"
+
+static bool __guc_rc_supported(struct intel_guc *guc)
+{
+	/* GuC RC is unavailable for pre-Gen12 */
+	return guc->submission_supported &&
+		GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12;
+}
+
+static bool __guc_rc_selected(struct intel_guc *guc)
+{
+	if (!intel_guc_rc_is_supported(guc))
+		return false;
+
+	return guc->submission_selected;
+}
+
+void intel_guc_rc_init_early(struct intel_guc *guc)
+{
+	guc->rc_supported = __guc_rc_supported(guc);
+	guc->rc_selected = __guc_rc_selected(guc);
+}
+
+static int guc_action_control_gucrc(struct intel_guc *guc, bool enable)
+{
+	struct drm_device *drm = &guc_to_gt(guc)->i915->drm;
+	u32 rc_mode = enable ? INTEL_GUCRC_FIRMWARE_CONTROL :
+				INTEL_GUCRC_HOST_CONTROL;
+	u32 action[] = {
+		INTEL_GUC_ACTION_SETUP_PC_GUCRC,
+		rc_mode
+	};
+	int ret;
+
+	ret = intel_guc_send(guc, action, ARRAY_SIZE(action));
+	if (ret)
+		drm_err(drm, "Failed to set GUCRC mode(%d), err=%d\n",
+			rc_mode, ret);
+
+	return ret;
+}
+
+static int __guc_rc_control(struct intel_guc *guc, bool enable)
+{
+	struct intel_gt *gt = guc_to_gt(guc);
+	int ret;
+
+	if (!intel_uc_uses_guc_rc(&gt->uc))
+		return -ENOTSUPP;
+
+	if (!intel_guc_is_ready(guc))
+		return -EINVAL;
+
+	ret = guc_action_control_gucrc(guc, enable);
+	if (unlikely(ret))
+		return ret;
+
+	drm_info(&gt->i915->drm, "GuC RC %s\n",
+	         enableddisabled(enable));
+
+	return 0;
+}
+
+int intel_guc_rc_enable(struct intel_guc *guc)
+{
+	return __guc_rc_control(guc, true);
+}
+
+int intel_guc_rc_disable(struct intel_guc *guc)
+{
+	return __guc_rc_control(guc, false);
+}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h
new file mode 100644
index 000000000000..169e60726e5b
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#ifndef _INTEL_GUC_RC_H_
+#define _INTEL_GUC_RC_H_
+
+#include <linux/types.h>
+#include "intel_guc_submission.h"
+
+void intel_guc_rc_init_early(struct intel_guc *guc);
+
+static inline bool intel_guc_rc_is_supported(struct intel_guc *guc)
+{
+	return guc->rc_supported;
+}
+
+static inline bool intel_guc_rc_is_wanted(struct intel_guc *guc)
+{
+	return guc->submission_selected && intel_guc_rc_is_supported(guc);
+}
+
+static inline bool intel_guc_rc_is_used(struct intel_guc *guc)
+{
+	return intel_guc_submission_is_used(guc) && intel_guc_rc_is_wanted(guc);
+}
+
+int intel_guc_rc_enable(struct intel_guc *guc);
+int intel_guc_rc_disable(struct intel_guc *guc);
+
+#endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.h b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
index 38e465fd8a0c..29d8ad6d9087 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
@@ -7,6 +7,7 @@
 #define _INTEL_UC_H_
 
 #include "intel_guc.h"
+#include "intel_guc_rc.h"
 #include "intel_guc_submission.h"
 #include "intel_huc.h"
 #include "i915_params.h"
@@ -84,6 +85,7 @@ uc_state_checkers(guc, guc);
 uc_state_checkers(huc, huc);
 uc_state_checkers(guc, guc_submission);
 uc_state_checkers(guc, guc_slpc);
+uc_state_checkers(guc, guc_rc);
 
 #undef uc_state_checkers
 #undef __uc_state_checker
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* Re: [PATCH 08/16] drm/i915/guc/slpc: Add methods to set min/max frequency
  2021-07-10  1:20 ` [PATCH 08/16] drm/i915/guc/slpc: Add methods to set min/max frequency Vinay Belgaumkar
@ 2021-07-10  3:07   ` kernel test robot
  2021-07-10  5:17   ` kernel test robot
  2021-07-10 17:47   ` Michal Wajdeczko
  2 siblings, 0 replies; 49+ messages in thread
From: kernel test robot @ 2021-07-10  3:07 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel
  Cc: Vinay Belgaumkar, Sundaresan Sujaritha, kbuild-all

[-- Attachment #1: Type: text/plain, Size: 4028 bytes --]

Hi Vinay,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm-tip/drm-tip]
[cannot apply to drm-intel/for-linux-next drm-exynos/exynos-drm-next tegra-drm/drm/tegra/for-next drm/drm-next v5.13 next-20210709]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Vinay-Belgaumkar/Enable-GuC-based-power-management-features/20210710-092520
base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
config: x86_64-allyesconfig (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/ce93ba218ad070e0b1ae6f9823820fb4d2e14a8b
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Vinay-Belgaumkar/Enable-GuC-based-power-management-features/20210710-092520
        git checkout ce93ba218ad070e0b1ae6f9823820fb4d2e14a8b
        # save the attached .config to linux build tree
        mkdir build_dir
        make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/gpu/drm/i915/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c:258: warning: expecting prototype for intel_guc_slpc_max_freq_set(). Prototype was for intel_guc_slpc_set_max_freq() instead
>> drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c:292: warning: expecting prototype for intel_guc_slpc_min_freq_set(). Prototype was for intel_guc_slpc_set_min_freq() instead


vim +258 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c

   246	
   247	/**
   248	 * intel_guc_slpc_max_freq_set() - Set max frequency limit for SLPC.
   249	 * @slpc: pointer to intel_guc_slpc.
   250	 * @val: encoded frequency
   251	 *
   252	 * This function will invoke GuC SLPC action to update the max frequency
   253	 * limit for slice and unslice.
   254	 *
   255	 * Return: 0 on success, non-zero error code on failure.
   256	 */
   257	int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val)
 > 258	{
   259		int ret;
   260		struct drm_i915_private *i915 = slpc_to_i915(slpc);
   261		intel_wakeref_t wakeref;
   262	
   263		wakeref = intel_runtime_pm_get(&i915->runtime_pm);
   264	
   265		ret = slpc_set_param(slpc,
   266			       SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ,
   267			       val);
   268	
   269		if (ret) {
   270			drm_err(&i915->drm,
   271				"Set max frequency unslice returned %d", ret);
   272			ret = -EIO;
   273			goto done;
   274		}
   275	
   276	done:
   277		intel_runtime_pm_put(&i915->runtime_pm, wakeref);
   278		return ret;
   279	}
   280	
   281	/**
   282	 * intel_guc_slpc_min_freq_set() - Set min frequency limit for SLPC.
   283	 * @slpc: pointer to intel_guc_slpc.
   284	 * @val: encoded frequency
   285	 *
   286	 * This function will invoke GuC SLPC action to update the min frequency
   287	 * limit.
   288	 *
   289	 * Return: 0 on success, non-zero error code on failure.
   290	 */
   291	int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val)
 > 292	{
   293		int ret;
   294		struct intel_guc *guc = slpc_to_guc(slpc);
   295		struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
   296		intel_wakeref_t wakeref;
   297	
   298		wakeref = intel_runtime_pm_get(&i915->runtime_pm);
   299	
   300		ret = slpc_set_param(slpc,
   301			       SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
   302			       val);
   303		if (ret) {
   304			drm_err(&i915->drm,
   305				"Set min frequency for unslice returned %d", ret);
   306			ret = -EIO;
   307			goto done;
   308		}
   309	
   310	done:
   311		intel_runtime_pm_put(&i915->runtime_pm, wakeref);
   312		return ret;
   313	}
   314	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 66092 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 08/16] drm/i915/guc/slpc: Add methods to set min/max frequency
  2021-07-10  1:20 ` [PATCH 08/16] drm/i915/guc/slpc: Add methods to set min/max frequency Vinay Belgaumkar
  2021-07-10  3:07   ` kernel test robot
@ 2021-07-10  5:17   ` kernel test robot
  2021-07-10 17:47   ` Michal Wajdeczko
  2 siblings, 0 replies; 49+ messages in thread
From: kernel test robot @ 2021-07-10  5:17 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel
  Cc: clang-built-linux, Sundaresan Sujaritha, kbuild-all, Vinay Belgaumkar

[-- Attachment #1: Type: text/plain, Size: 4415 bytes --]

Hi Vinay,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm-tip/drm-tip]
[cannot apply to drm-intel/for-linux-next drm-exynos/exynos-drm-next tegra-drm/drm/tegra/for-next drm/drm-next v5.13 next-20210709]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Vinay-Belgaumkar/Enable-GuC-based-power-management-features/20210710-092520
base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
config: x86_64-randconfig-a014-20210709 (attached as .config)
compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project 8d69635ed9ecf36fd0ca85906bfde17949671cbe)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # https://github.com/0day-ci/linux/commit/ce93ba218ad070e0b1ae6f9823820fb4d2e14a8b
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Vinay-Belgaumkar/Enable-GuC-based-power-management-features/20210710-092520
        git checkout ce93ba218ad070e0b1ae6f9823820fb4d2e14a8b
        # save the attached .config to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/gpu/drm/i915/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c:258: warning: expecting prototype for intel_guc_slpc_max_freq_set(). Prototype was for intel_guc_slpc_set_max_freq() instead
>> drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c:292: warning: expecting prototype for intel_guc_slpc_min_freq_set(). Prototype was for intel_guc_slpc_set_min_freq() instead


vim +258 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c

   246	
   247	/**
   248	 * intel_guc_slpc_max_freq_set() - Set max frequency limit for SLPC.
   249	 * @slpc: pointer to intel_guc_slpc.
   250	 * @val: encoded frequency
   251	 *
   252	 * This function will invoke GuC SLPC action to update the max frequency
   253	 * limit for slice and unslice.
   254	 *
   255	 * Return: 0 on success, non-zero error code on failure.
   256	 */
   257	int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val)
 > 258	{
   259		int ret;
   260		struct drm_i915_private *i915 = slpc_to_i915(slpc);
   261		intel_wakeref_t wakeref;
   262	
   263		wakeref = intel_runtime_pm_get(&i915->runtime_pm);
   264	
   265		ret = slpc_set_param(slpc,
   266			       SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ,
   267			       val);
   268	
   269		if (ret) {
   270			drm_err(&i915->drm,
   271				"Set max frequency unslice returned %d", ret);
   272			ret = -EIO;
   273			goto done;
   274		}
   275	
   276	done:
   277		intel_runtime_pm_put(&i915->runtime_pm, wakeref);
   278		return ret;
   279	}
   280	
   281	/**
   282	 * intel_guc_slpc_min_freq_set() - Set min frequency limit for SLPC.
   283	 * @slpc: pointer to intel_guc_slpc.
   284	 * @val: encoded frequency
   285	 *
   286	 * This function will invoke GuC SLPC action to update the min frequency
   287	 * limit.
   288	 *
   289	 * Return: 0 on success, non-zero error code on failure.
   290	 */
   291	int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val)
 > 292	{
   293		int ret;
   294		struct intel_guc *guc = slpc_to_guc(slpc);
   295		struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
   296		intel_wakeref_t wakeref;
   297	
   298		wakeref = intel_runtime_pm_get(&i915->runtime_pm);
   299	
   300		ret = slpc_set_param(slpc,
   301			       SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
   302			       val);
   303		if (ret) {
   304			drm_err(&i915->drm,
   305				"Set min frequency for unslice returned %d", ret);
   306			ret = -EIO;
   307			goto done;
   308		}
   309	
   310	done:
   311		intel_runtime_pm_put(&i915->runtime_pm, wakeref);
   312		return ret;
   313	}
   314	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 52225 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc
  2021-07-10  1:20 ` [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc Vinay Belgaumkar
@ 2021-07-10  6:18   ` kernel test robot
  2021-07-10  7:30   ` kernel test robot
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 49+ messages in thread
From: kernel test robot @ 2021-07-10  6:18 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel
  Cc: clang-built-linux, Sujaritha Sundaresan, kbuild-all,
	Tvrtko Ursulin, Vinay Belgaumkar

[-- Attachment #1: Type: text/plain, Size: 3860 bytes --]

Hi Vinay,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm-tip/drm-tip]
[cannot apply to drm-intel/for-linux-next drm-exynos/exynos-drm-next tegra-drm/drm/tegra/for-next drm/drm-next v5.13 next-20210709]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Vinay-Belgaumkar/Enable-GuC-based-power-management-features/20210710-092520
base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
config: x86_64-randconfig-a014-20210709 (attached as .config)
compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project 8d69635ed9ecf36fd0ca85906bfde17949671cbe)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # https://github.com/0day-ci/linux/commit/8388422991b4e0e4da460328634a7ec1d278de6a
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Vinay-Belgaumkar/Enable-GuC-based-power-management-features/20210710-092520
        git checkout 8388422991b4e0e4da460328634a7ec1d278de6a
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/gpu/drm/i915/gt/intel_rps.c:1969:5: warning: no previous prototype for function 'intel_rps_read_punit_req' [-Wmissing-prototypes]
   u32 intel_rps_read_punit_req(struct intel_rps *rps)
       ^
   drivers/gpu/drm/i915/gt/intel_rps.c:1969:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   u32 intel_rps_read_punit_req(struct intel_rps *rps)
   ^
   static 
>> drivers/gpu/drm/i915/gt/intel_rps.c:1978:5: warning: no previous prototype for function 'intel_rps_get_req' [-Wmissing-prototypes]
   u32 intel_rps_get_req(struct intel_rps *rps, u32 pureq)
       ^
   drivers/gpu/drm/i915/gt/intel_rps.c:1978:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   u32 intel_rps_get_req(struct intel_rps *rps, u32 pureq)
   ^
   static 
>> drivers/gpu/drm/i915/gt/intel_rps.c:1985:5: warning: no previous prototype for function 'intel_rps_read_punit_req_frequency' [-Wmissing-prototypes]
   u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps)
       ^
   drivers/gpu/drm/i915/gt/intel_rps.c:1985:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps)
   ^
   static 
   3 warnings generated.


vim +/intel_rps_read_punit_req +1969 drivers/gpu/drm/i915/gt/intel_rps.c

  1968	
> 1969	u32 intel_rps_read_punit_req(struct intel_rps *rps)
  1970	{
  1971		struct intel_uncore *uncore = rps_to_uncore(rps);
  1972	
  1973		u32 pureq = intel_uncore_read(uncore, GEN6_RPNSWREQ);
  1974	
  1975		return pureq;
  1976	}
  1977	
> 1978	u32 intel_rps_get_req(struct intel_rps *rps, u32 pureq)
  1979	{
  1980		u32 req = pureq >> GEN9_SW_REQ_UNSLICE_RATIO_SHIFT;
  1981	
  1982		return req;
  1983	}
  1984	
> 1985	u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps)
  1986	{
  1987		u32 freq = intel_rps_get_req(rps, intel_rps_read_punit_req(rps));
  1988	
  1989		return intel_gpu_freq(rps, freq);
  1990	}
  1991	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 52225 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc
  2021-07-10  1:20 ` [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc Vinay Belgaumkar
  2021-07-10  6:18   ` kernel test robot
@ 2021-07-10  7:30   ` kernel test robot
  2021-07-10  7:30   ` [RFC PATCH] drm/i915/guc/slpc: intel_rps_read_punit_req() can be static kernel test robot
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 49+ messages in thread
From: kernel test robot @ 2021-07-10  7:30 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel
  Cc: Vinay Belgaumkar, Sujaritha Sundaresan, kbuild-all, Tvrtko Ursulin

[-- Attachment #1: Type: text/plain, Size: 1786 bytes --]

Hi Vinay,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm-tip/drm-tip]
[cannot apply to drm-intel/for-linux-next drm-exynos/exynos-drm-next tegra-drm/drm/tegra/for-next drm/drm-next v5.13 next-20210709]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Vinay-Belgaumkar/Enable-GuC-based-power-management-features/20210710-092520
base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
config: x86_64-randconfig-s021-20210709 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.3-341-g8af24329-dirty
        # https://github.com/0day-ci/linux/commit/8388422991b4e0e4da460328634a7ec1d278de6a
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Vinay-Belgaumkar/Enable-GuC-based-power-management-features/20210710-092520
        git checkout 8388422991b4e0e4da460328634a7ec1d278de6a
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/gpu/drm/i915/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
>> drivers/gpu/drm/i915/gt/intel_rps.c:1978:5: sparse: sparse: symbol 'intel_rps_get_req' was not declared. Should it be static?

Please review and possibly fold the followup patch.

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 46082 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [RFC PATCH] drm/i915/guc/slpc: intel_rps_read_punit_req() can be static
  2021-07-10  1:20 ` [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc Vinay Belgaumkar
  2021-07-10  6:18   ` kernel test robot
  2021-07-10  7:30   ` kernel test robot
@ 2021-07-10  7:30   ` kernel test robot
  2021-07-10 13:54   ` [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc kernel test robot
  2021-07-10 18:20   ` Michal Wajdeczko
  4 siblings, 0 replies; 49+ messages in thread
From: kernel test robot @ 2021-07-10  7:30 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel
  Cc: Vinay Belgaumkar, Sujaritha Sundaresan, kbuild-all, Tvrtko Ursulin

drivers/gpu/drm/i915/gt/intel_rps.c:1969:5: warning: symbol 'intel_rps_read_punit_req' was not declared. Should it be static?
drivers/gpu/drm/i915/gt/intel_rps.c:1978:5: warning: symbol 'intel_rps_get_req' was not declared. Should it be static?

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: kernel test robot <lkp@intel.com>
---
 intel_rps.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c
index 88ffc5d90730a..a78af6b0babea 100644
--- a/drivers/gpu/drm/i915/gt/intel_rps.c
+++ b/drivers/gpu/drm/i915/gt/intel_rps.c
@@ -1966,7 +1966,7 @@ u32 intel_rps_read_actual_frequency(struct intel_rps *rps)
 	return freq;
 }
 
-u32 intel_rps_read_punit_req(struct intel_rps *rps)
+static u32 intel_rps_read_punit_req(struct intel_rps *rps)
 {
 	struct intel_uncore *uncore = rps_to_uncore(rps);
 
@@ -1975,7 +1975,7 @@ u32 intel_rps_read_punit_req(struct intel_rps *rps)
 	return pureq;
 }
 
-u32 intel_rps_get_req(struct intel_rps *rps, u32 pureq)
+static u32 intel_rps_get_req(struct intel_rps *rps, u32 pureq)
 {
 	u32 req = pureq >> GEN9_SW_REQ_UNSLICE_RATIO_SHIFT;
 

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* Re: [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc
  2021-07-10  1:20 ` [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc Vinay Belgaumkar
                     ` (2 preceding siblings ...)
  2021-07-10  7:30   ` [RFC PATCH] drm/i915/guc/slpc: intel_rps_read_punit_req() can be static kernel test robot
@ 2021-07-10 13:54   ` kernel test robot
  2021-07-10 18:20   ` Michal Wajdeczko
  4 siblings, 0 replies; 49+ messages in thread
From: kernel test robot @ 2021-07-10 13:54 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel
  Cc: Vinay Belgaumkar, Sujaritha Sundaresan, kbuild-all, Tvrtko Ursulin

[-- Attachment #1: Type: text/plain, Size: 2888 bytes --]

Hi Vinay,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm-tip/drm-tip]
[cannot apply to drm-intel/for-linux-next drm-exynos/exynos-drm-next tegra-drm/drm/tegra/for-next drm/drm-next v5.13 next-20210709]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Vinay-Belgaumkar/Enable-GuC-based-power-management-features/20210710-092520
base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
config: x86_64-randconfig-a004-20210709 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/8388422991b4e0e4da460328634a7ec1d278de6a
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Vinay-Belgaumkar/Enable-GuC-based-power-management-features/20210710-092520
        git checkout 8388422991b4e0e4da460328634a7ec1d278de6a
        # save the attached .config to linux build tree
        make W=1 ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/gpu/drm/i915/gt/intel_rps.c:1969:5: warning: no previous prototype for 'intel_rps_read_punit_req' [-Wmissing-prototypes]
    1969 | u32 intel_rps_read_punit_req(struct intel_rps *rps)
         |     ^~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/gpu/drm/i915/gt/intel_rps.c:1978:5: warning: no previous prototype for 'intel_rps_get_req' [-Wmissing-prototypes]
    1978 | u32 intel_rps_get_req(struct intel_rps *rps, u32 pureq)
         |     ^~~~~~~~~~~~~~~~~
>> drivers/gpu/drm/i915/gt/intel_rps.c:1985:5: warning: no previous prototype for 'intel_rps_read_punit_req_frequency' [-Wmissing-prototypes]
    1985 | u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps)
         |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


vim +/intel_rps_read_punit_req +1969 drivers/gpu/drm/i915/gt/intel_rps.c

  1968	
> 1969	u32 intel_rps_read_punit_req(struct intel_rps *rps)
  1970	{
  1971		struct intel_uncore *uncore = rps_to_uncore(rps);
  1972	
  1973		u32 pureq = intel_uncore_read(uncore, GEN6_RPNSWREQ);
  1974	
  1975		return pureq;
  1976	}
  1977	
> 1978	u32 intel_rps_get_req(struct intel_rps *rps, u32 pureq)
  1979	{
  1980		u32 req = pureq >> GEN9_SW_REQ_UNSLICE_RATIO_SHIFT;
  1981	
  1982		return req;
  1983	}
  1984	
> 1985	u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps)
  1986	{
  1987		u32 freq = intel_rps_get_req(rps, intel_rps_read_punit_req(rps));
  1988	
  1989		return intel_gpu_freq(rps, freq);
  1990	}
  1991	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 41972 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 02/16] drm/i915/guc/slpc: Initial definitions for slpc
  2021-07-10  1:20 ` [PATCH 02/16] drm/i915/guc/slpc: Initial definitions for slpc Vinay Belgaumkar
@ 2021-07-10 14:27   ` Michal Wajdeczko
  2021-07-12 18:40     ` Belgaumkar, Vinay
  2021-07-12 23:43     ` Belgaumkar, Vinay
  0 siblings, 2 replies; 49+ messages in thread
From: Michal Wajdeczko @ 2021-07-10 14:27 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel
  Cc: Daniele Ceraolo Spurio, Sundaresan Sujaritha

Hi Vinay,

On 10.07.2021 03:20, Vinay Belgaumkar wrote:
> Add macros to check for slpc support. This feature is currently supported
> for gen12+ and enabled whenever guc submission is enabled/selected.

please try to use consistent names across all patches:

s/slpc/SLPC
s/gen12/Gen12
s/guc/GuC

> 
> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc.c        |  1 +
>  drivers/gpu/drm/i915/gt/uc/intel_guc.h        |  2 ++
>  .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 21 +++++++++++++++++++
>  .../gpu/drm/i915/gt/uc/intel_guc_submission.h | 16 ++++++++++++++
>  drivers/gpu/drm/i915/gt/uc/intel_uc.c         |  6 ++++--
>  drivers/gpu/drm/i915/gt/uc/intel_uc.h         |  1 +
>  6 files changed, 45 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> index 979128e28372..b9a809f2d221 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> @@ -157,6 +157,7 @@ void intel_guc_init_early(struct intel_guc *guc)
>  	intel_guc_ct_init_early(&guc->ct);
>  	intel_guc_log_init_early(&guc->log);
>  	intel_guc_submission_init_early(guc);
> +	intel_guc_slpc_init_early(guc);
>  
>  	mutex_init(&guc->send_mutex);
>  	spin_lock_init(&guc->irq_lock);
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> index 5d94cf482516..e5a456918b88 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> @@ -57,6 +57,8 @@ struct intel_guc {
>  
>  	bool submission_supported;
>  	bool submission_selected;
> +	bool slpc_supported;
> +	bool slpc_selected;
>  
>  	struct i915_vma *ads_vma;
>  	struct __guc_ads_blob *ads_blob;
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
> index 9c102bf0c8e3..e2644a05f298 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
> @@ -2351,6 +2351,27 @@ void intel_guc_submission_init_early(struct intel_guc *guc)
>  	guc->submission_selected = __guc_submission_selected(guc);
>  }
>  
> +static bool __guc_slpc_supported(struct intel_guc *guc)

hmm, easy to confuse with intel_guc_slpc_is_supported, so maybe:

__detect_slpc_supported()

(yes, I know you were following code above)

> +{
> +	/* GuC slpc is unavailable for pre-Gen12 */

s/slpc/SLPC

> +	return guc->submission_supported &&
> +		GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12;
> +}
> +
> +static bool __guc_slpc_selected(struct intel_guc *guc)
> +{
> +	if (!intel_guc_slpc_is_supported(guc))
> +		return false;
> +
> +	return guc->submission_selected;
> +}
> +
> +void intel_guc_slpc_init_early(struct intel_guc *guc)
> +{
> +	guc->slpc_supported = __guc_slpc_supported(guc);
> +	guc->slpc_selected = __guc_slpc_selected(guc);
> +}

in patch 4/16 you are introducing intel_guc_slpc.c|h so to have proper
encapsulation better to define this function as

void intel_guc_slpc_init_early(struct intel_guc_slpc *slpc) { }

and move it to intel_guc_slpc.c

> +
>  static inline struct intel_context *
>  g2h_context_lookup(struct intel_guc *guc, u32 desc_idx)
>  {
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
> index be767eb6ff71..7ae5fd052faf 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
> @@ -13,6 +13,7 @@
>  struct drm_printer;
>  struct intel_engine_cs;
>  
> +void intel_guc_slpc_init_early(struct intel_guc *guc);

it really does not belong to this .h

>  void intel_guc_submission_init_early(struct intel_guc *guc);
>  int intel_guc_submission_init(struct intel_guc *guc);
>  void intel_guc_submission_enable(struct intel_guc *guc);
> @@ -50,4 +51,19 @@ static inline bool intel_guc_submission_is_used(struct intel_guc *guc)
>  	return intel_guc_is_used(guc) && intel_guc_submission_is_wanted(guc);
>  }
>  
> +static inline bool intel_guc_slpc_is_supported(struct intel_guc *guc)
> +{
> +	return guc->slpc_supported;
> +}
> +
> +static inline bool intel_guc_slpc_is_wanted(struct intel_guc *guc)
> +{
> +	return guc->slpc_selected;
> +}
> +
> +static inline bool intel_guc_slpc_is_used(struct intel_guc *guc)
> +{
> +	return intel_guc_submission_is_used(guc) && intel_guc_slpc_is_wanted(guc);
> +}

did you try to define them in intel_guc_slpc.h ?

note that to avoid circular dependencies you can define slpc struct in
intel_guc_slpc_types.h and then

in intel_guc.h:
	#include "intel_guc_slpc_types.h" instead of intel_guc_slpc.h

in intel_guc_slpc.h:
	#include "intel_guc.h"
	#include "intel_guc_slpc_types.h"
	#include "intel_guc_submission.h"

> +
>  #endif
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
> index 61be0aa81492..dca5f6d0641b 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
> @@ -76,16 +76,18 @@ static void __confirm_options(struct intel_uc *uc)
>  	struct drm_i915_private *i915 = uc_to_gt(uc)->i915;
>  
>  	drm_dbg(&i915->drm,
> -		"enable_guc=%d (guc:%s submission:%s huc:%s)\n",
> +		"enable_guc=%d (guc:%s submission:%s huc:%s slpc:%s)\n",
>  		i915->params.enable_guc,
>  		yesno(intel_uc_wants_guc(uc)),
>  		yesno(intel_uc_wants_guc_submission(uc)),
> -		yesno(intel_uc_wants_huc(uc)));
> +		yesno(intel_uc_wants_huc(uc)),
> +		yesno(intel_uc_wants_guc_slpc(uc)));
>  
>  	if (i915->params.enable_guc == 0) {
>  		GEM_BUG_ON(intel_uc_wants_guc(uc));
>  		GEM_BUG_ON(intel_uc_wants_guc_submission(uc));
>  		GEM_BUG_ON(intel_uc_wants_huc(uc));
> +		GEM_BUG_ON(intel_uc_wants_guc_slpc(uc));
>  		return;
>  	}
>  
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.h b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
> index e2da2b6e76e1..38e465fd8a0c 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
> @@ -83,6 +83,7 @@ __uc_state_checker(x, func, uses, used)
>  uc_state_checkers(guc, guc);
>  uc_state_checkers(huc, huc);
>  uc_state_checkers(guc, guc_submission);
> +uc_state_checkers(guc, guc_slpc);
>  
>  #undef uc_state_checkers
>  #undef __uc_state_checker
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Intel-gfx] [PATCH 04/16] drm/i915/guc/slpc: Lay out slpc init/enable/disable/fini
  2021-07-10  1:20 ` [PATCH 04/16] drm/i915/guc/slpc: Lay out slpc init/enable/disable/fini Vinay Belgaumkar
@ 2021-07-10 14:35   ` Michal Wajdeczko
  2021-07-13  0:37     ` Belgaumkar, Vinay
  0 siblings, 1 reply; 49+ messages in thread
From: Michal Wajdeczko @ 2021-07-10 14:35 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel



On 10.07.2021 03:20, Vinay Belgaumkar wrote:
> Declare header and source files for SLPC, along with init and
> enable/disable function templates.

later you claim that "disable" is not needed

> 
> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile               |  1 +
>  drivers/gpu/drm/i915/gt/uc/intel_guc.h      |  2 ++
>  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 34 +++++++++++++++++++++
>  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 16 ++++++++++
>  4 files changed, 53 insertions(+)
>  create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>  create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index ab7679957623..d8eac4468df9 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -186,6 +186,7 @@ i915-y += gt/uc/intel_uc.o \
>  	  gt/uc/intel_guc_fw.o \
>  	  gt/uc/intel_guc_log.o \
>  	  gt/uc/intel_guc_log_debugfs.o \
> +	  gt/uc/intel_guc_slpc.o \
>  	  gt/uc/intel_guc_submission.o \
>  	  gt/uc/intel_huc.o \
>  	  gt/uc/intel_huc_debugfs.o \
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> index e5a456918b88..0dbbd9cf553f 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> @@ -15,6 +15,7 @@
>  #include "intel_guc_ct.h"
>  #include "intel_guc_log.h"
>  #include "intel_guc_reg.h"
> +#include "intel_guc_slpc.h"
>  #include "intel_uc_fw.h"
>  #include "i915_utils.h"
>  #include "i915_vma.h"
> @@ -30,6 +31,7 @@ struct intel_guc {
>  	struct intel_uc_fw fw;
>  	struct intel_guc_log log;
>  	struct intel_guc_ct ct;
> +	struct intel_guc_slpc slpc;
>  
>  	/* Global engine used to submit requests to GuC */
>  	struct i915_sched_engine *sched_engine;
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> new file mode 100644
> index 000000000000..c1f569d2300d
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> @@ -0,0 +1,34 @@
> +/*
> + * SPDX-License-Identifier: MIT

SPDX tag shall be in very first line, for .c:

// SPDX-License-Identifier: MIT

> + *
> + * Copyright © 2020 Intel Corporation

2021

> + */
> +
> +#include "intel_guc_slpc.h"
> +
> +int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
> +{
> +	return 0;
> +}
> +
> +/*
> + * intel_guc_slpc_enable() - Start SLPC
> + * @slpc: pointer to intel_guc_slpc.
> + *
> + * SLPC is enabled by setting up the shared data structure and
> + * sending reset event to GuC SLPC. Initial data is setup in
> + * intel_guc_slpc_init. Here we send the reset event. We do
> + * not currently need a slpc_disable since this is taken care
> + * of automatically when a reset/suspend occurs and the guc

s/guc/GuC

> + * channels are destroyed.

you mean CTB ?

> + *
> + * Return: 0 on success, non-zero error code on failure.
> + */
> +int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
> +{
> +	return 0;
> +}
> +
> +void intel_guc_slpc_fini(struct intel_guc_slpc *slpc)
> +{
> +}
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> new file mode 100644
> index 000000000000..74fd86769163
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> @@ -0,0 +1,16 @@
> +/*
> + * SPDX-License-Identifier: MIT

SPDX tag shall be in very first line, for .h:

/* SPDX-License-Identifier: MIT */

> + *
> + * Copyright © 2020 Intel Corporation

2021

> + */
> +#ifndef _INTEL_GUC_SLPC_H_
> +#define _INTEL_GUC_SLPC_H_
> +
> +struct intel_guc_slpc {
> +};

move all data definitions to intel_guc_slpc_types.h and include it here

> +
> +int intel_guc_slpc_init(struct intel_guc_slpc *slpc);
> +int intel_guc_slpc_enable(struct intel_guc_slpc *slpc);
> +void intel_guc_slpc_fini(struct intel_guc_slpc *slpc);
> +
> +#endif
> 

and as suggested in comment to 2/14 you should likely move this patch to
the front of the series

Michal


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 05/16] drm/i915/guc/slpc: Adding slpc communication interfaces
  2021-07-10  1:20 ` [PATCH 05/16] drm/i915/guc/slpc: Adding slpc communication interfaces Vinay Belgaumkar
@ 2021-07-10 15:52   ` Michal Wajdeczko
  2021-07-13 23:22     ` Belgaumkar, Vinay
  0 siblings, 1 reply; 49+ messages in thread
From: Michal Wajdeczko @ 2021-07-10 15:52 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel; +Cc: Sundaresan Sujaritha



On 10.07.2021 03:20, Vinay Belgaumkar wrote:
> Replicate the SLPC header file in GuC for the most part. There are

what you mean by "replicate" here?

> some SLPC mode based parameters which haven't been included since
> we are not using them.
> 
> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc.c        |   4 +
>  drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h   |   2 +
>  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h   |   2 +
>  .../gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h  | 255 ++++++++++++++++++
>  4 files changed, 263 insertions(+)
>  create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> index b9a809f2d221..9d61b2d54de4 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> @@ -202,11 +202,15 @@ static u32 guc_ctl_debug_flags(struct intel_guc *guc)
>  
>  static u32 guc_ctl_feature_flags(struct intel_guc *guc)
>  {
> +	struct intel_gt *gt = guc_to_gt(guc);
>  	u32 flags = 0;
>  
>  	if (!intel_guc_submission_is_used(guc))
>  		flags |= GUC_CTL_DISABLE_SCHEDULER;
>  
> +	if (intel_uc_uses_guc_slpc(&gt->uc))
> +		flags |= GUC_CTL_ENABLE_SLPC;
> +
>  	return flags;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> index 94bb1ca6f889..19e2504d7a36 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> @@ -114,6 +114,8 @@
>  #define   GUC_ADS_ADDR_SHIFT		1
>  #define   GUC_ADS_ADDR_MASK		(0xFFFFF << GUC_ADS_ADDR_SHIFT)
>  
> +#define GUC_CTL_ENABLE_SLPC            BIT(2)

this should be defined closer to GUC_CTL_FEATURE

> +
>  #define GUC_CTL_MAX_DWORDS		(SOFT_SCRATCH_COUNT - 2) /* [1..14] */
>  
>  /* Generic GT SysInfo data types */
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> index 74fd86769163..98036459a1a3 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> @@ -6,6 +6,8 @@
>  #ifndef _INTEL_GUC_SLPC_H_
>  #define _INTEL_GUC_SLPC_H_
>  
> +#include "intel_guc_slpc_fwif.h"

doesn't seem to be needed right now

> +
>  struct intel_guc_slpc {
>  };
>  
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h
> new file mode 100644
> index 000000000000..2a5e71428374
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h

I've started to move all pure ABI definitions to files in abi/ folder,
leaving in guc_fwif.h only our next level helpers/wrappers.

Can you move these SLPC definition there too ? maybe as dedicated:

	abi/guc_slpc_abi.h

> @@ -0,0 +1,255 @@
> +/*
> + * SPDX-License-Identifier: MIT

use proper format

> + *
> + * Copyright © 2020 Intel Corporation

2021

> + */
> +#ifndef _INTEL_GUC_SLPC_FWIF_H_
> +#define _INTEL_GUC_SLPC_FWIF_H_
> +
> +#include <linux/types.h>
> +
> +/* This file replicates the header in GuC code for handling SLPC related
> + * data structures and sizes
> + */

use proper format for multi-line comments:

	/*
	 * blah blah
	 * blah blah
	 */

> +
> +/* SLPC exposes certain parameters for global configuration by the host.
> + * These are referred to as override parameters, because in most cases
> + * the host will not need to modify the default values used by SLPC.
> + * SLPC remembers the default values which allows the host to easily restore
> + * them by simply unsetting the override. The host can set or unset override
> + * parameters during SLPC (re-)initialization using the SLPC Reset event.
> + * The host can also set or unset override parameters on the fly using the
> + * Parameter Set and Parameter Unset events
> + */
> +#define SLPC_MAX_OVERRIDE_PARAMETERS	256
> +#define SLPC_OVERRIDE_BITFIELD_SIZE \
> +		(SLPC_MAX_OVERRIDE_PARAMETERS / 32)
> +
> +#define SLPC_PAGE_SIZE_BYTES			4096
> +#define SLPC_CACHELINE_SIZE_BYTES		64
> +#define SLPC_SHARE_DATA_SIZE_BYTE_HEADER	SLPC_CACHELINE_SIZE_BYTES
> +#define SLPC_SHARE_DATA_SIZE_BYTE_PLATFORM_INFO	SLPC_CACHELINE_SIZE_BYTES
> +#define SLPC_SHARE_DATA_SIZE_BYTE_TASK_STATE	SLPC_CACHELINE_SIZE_BYTES
> +#define SLPC_SHARE_DATA_MODE_DEFN_TABLE_SIZE	SLPC_PAGE_SIZE_BYTES

can you put some simply diagram that would describe this layout ?

> +
> +#define SLPC_SHARE_DATA_SIZE_BYTE_MAX		(2 * SLPC_PAGE_SIZE_BYTES)
> +
> +/* Cacheline size aligned (Total size needed for
> + * SLPM_KMD_MAX_OVERRIDE_PARAMETERS=256 is 1088 bytes)
> + */
> +#define SLPC_SHARE_DATA_SIZE_BYTE_PARAM		(((((SLPC_MAX_OVERRIDE_PARAMETERS * 4) \
> +						+ ((SLPC_MAX_OVERRIDE_PARAMETERS / 32) * 4)) \
> +		+ (SLPC_CACHELINE_SIZE_BYTES-1)) / SLPC_CACHELINE_SIZE_BYTES)*SLPC_CACHELINE_SIZE_BYTES)
> +
> +#define SLPC_SHARE_DATA_SIZE_BYTE_OTHER		(SLPC_SHARE_DATA_SIZE_BYTE_MAX - \
> +					(SLPC_SHARE_DATA_SIZE_BYTE_HEADER \
> +					+ SLPC_SHARE_DATA_SIZE_BYTE_PLATFORM_INFO \
> +					+ SLPC_SHARE_DATA_SIZE_BYTE_TASK_STATE \
> +					+ SLPC_SHARE_DATA_SIZE_BYTE_PARAM \
> +					+ SLPC_SHARE_DATA_MODE_DEFN_TABLE_SIZE))
> +
> +#define SLPC_EVENT(id, argc)			((u32)(id) << 8 | (argc))
> +
> +#define SLPC_PARAM_TASK_DEFAULT			0
> +#define SLPC_PARAM_TASK_ENABLED			1
> +#define SLPC_PARAM_TASK_DISABLED		2
> +#define SLPC_PARAM_TASK_UNKNOWN			3

many values below are defined as enum, why these values are #defines ?

and is there any relation to these ones defined below (look similar)?

 +	SLPC_PARAM_TASK_ENABLE_GTPERF = 0,
 +	SLPC_PARAM_TASK_DISABLE_GTPERF = 1,
 +	SLPC_PARAM_TASK_ENABLE_BALANCER = 2,
 +	SLPC_PARAM_TASK_DISABLE_BALANCER = 3,
 +	SLPC_PARAM_TASK_ENABLE_DCC = 4,
 +	SLPC_PARAM_TASK_DISABLE_DCC = 5,

> +
> +enum slpc_status {
> +	SLPC_STATUS_OK = 0,
> +	SLPC_STATUS_ERROR = 1,
> +	SLPC_STATUS_ILLEGAL_COMMAND = 2,
> +	SLPC_STATUS_INVALID_ARGS = 3,
> +	SLPC_STATUS_INVALID_PARAMS = 4,
> +	SLPC_STATUS_INVALID_DATA = 5,
> +	SLPC_STATUS_OUT_OF_RANGE = 6,
> +	SLPC_STATUS_NOT_SUPPORTED = 7,
> +	SLPC_STATUS_NOT_IMPLEMENTED = 8,
> +	SLPC_STATUS_NO_DATA = 9,
> +	SLPC_STATUS_EVENT_NOT_REGISTERED = 10,
> +	SLPC_STATUS_REGISTER_LOCKED = 11,
> +	SLPC_STATUS_TEMPORARILY_UNAVAILABLE = 12,
> +	SLPC_STATUS_VALUE_ALREADY_SET = 13,
> +	SLPC_STATUS_VALUE_ALREADY_UNSET = 14,
> +	SLPC_STATUS_VALUE_NOT_CHANGED = 15,
> +	SLPC_STATUS_MEMIO_ERROR = 16,
> +	SLPC_STATUS_EVENT_QUEUED_REQ_DPC = 17,
> +	SLPC_STATUS_EVENT_QUEUED_NOREQ_DPC = 18,
> +	SLPC_STATUS_NO_EVENT_QUEUED = 19,
> +	SLPC_STATUS_OUT_OF_SPACE = 20,
> +	SLPC_STATUS_TIMEOUT = 21,
> +	SLPC_STATUS_NO_LOCK = 22,
> +	SLPC_STATUS_MAX
> +};
> +
> +enum slpc_event_id {
> +	SLPC_EVENT_RESET = 0,
> +	SLPC_EVENT_SHUTDOWN = 1,
> +	SLPC_EVENT_PLATFORM_INFO_CHANGE = 2,
> +	SLPC_EVENT_DISPLAY_MODE_CHANGE = 3,
> +	SLPC_EVENT_FLIP_COMPLETE = 4,
> +	SLPC_EVENT_QUERY_TASK_STATE = 5,
> +	SLPC_EVENT_PARAMETER_SET = 6,
> +	SLPC_EVENT_PARAMETER_UNSET = 7,
> +};
> +
> +enum slpc_param_id {
> +	SLPC_PARAM_TASK_ENABLE_GTPERF = 0,
> +	SLPC_PARAM_TASK_DISABLE_GTPERF = 1,
> +	SLPC_PARAM_TASK_ENABLE_BALANCER = 2,
> +	SLPC_PARAM_TASK_DISABLE_BALANCER = 3,
> +	SLPC_PARAM_TASK_ENABLE_DCC = 4,
> +	SLPC_PARAM_TASK_DISABLE_DCC = 5,
> +	SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ = 6,
> +	SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ = 7,
> +	SLPC_PARAM_GLOBAL_MIN_GT_SLICE_FREQ_MHZ = 8,
> +	SLPC_PARAM_GLOBAL_MAX_GT_SLICE_FREQ_MHZ = 9,
> +	SLPC_PARAM_GTPERF_THRESHOLD_MAX_FPS = 10,
> +	SLPC_PARAM_GLOBAL_DISABLE_GT_FREQ_MANAGEMENT = 11,
> +	SLPC_PARAM_GTPERF_ENABLE_FRAMERATE_STALLING = 12,
> +	SLPC_PARAM_GLOBAL_DISABLE_RC6_MODE_CHANGE = 13,
> +	SLPC_PARAM_GLOBAL_OC_UNSLICE_FREQ_MHZ = 14,
> +	SLPC_PARAM_GLOBAL_OC_SLICE_FREQ_MHZ = 15,
> +	SLPC_PARAM_GLOBAL_ENABLE_IA_GT_BALANCING = 16,
> +	SLPC_PARAM_GLOBAL_ENABLE_ADAPTIVE_BURST_TURBO = 17,
> +	SLPC_PARAM_GLOBAL_ENABLE_EVAL_MODE = 18,
> +	SLPC_PARAM_GLOBAL_ENABLE_BALANCER_IN_NON_GAMING_MODE = 19,
> +	SLPC_PARAM_GLOBAL_RT_MODE_TURBO_FREQ_DELTA_MHZ = 20,
> +	SLPC_PARAM_PWRGATE_RC_MODE = 21,
> +	SLPC_PARAM_EDR_MODE_COMPUTE_TIMEOUT_MS = 22,
> +	SLPC_PARAM_EDR_QOS_FREQ_MHZ = 23,
> +	SLPC_PARAM_MEDIA_FF_RATIO_MODE = 24,
> +	SLPC_PARAM_ENABLE_IA_FREQ_LIMITING = 25,
> +	SLPC_PARAM_STRATEGIES = 26,
> +	SLPC_PARAM_POWER_PROFILE = 27,
> +	SLPC_IGNORE_EFFICIENT_FREQUENCY = 28,

no PARAM tag inside this enum name

> +	SLPC_MAX_PARAM = 32,

can we move this out of enum, maybe as standalone #define ?
or remove it as doesn't seem to be useful at all

> +};
> +
> +enum slpc_global_state {
> +	SLPC_GLOBAL_STATE_NOT_RUNNING = 0,
> +	SLPC_GLOBAL_STATE_INITIALIZING = 1,
> +	SLPC_GLOBAL_STATE_RESETTING = 2,
> +	SLPC_GLOBAL_STATE_RUNNING = 3,
> +	SLPC_GLOBAL_STATE_SHUTTING_DOWN = 4,
> +	SLPC_GLOBAL_STATE_ERROR = 5
> +};
> +
> +enum slpc_platform_sku {
> +	SLPC_PLATFORM_SKU_UNDEFINED = 0,
> +	SLPC_PLATFORM_SKU_ULX = 1,
> +	SLPC_PLATFORM_SKU_ULT = 2,
> +	SLPC_PLATFORM_SKU_T = 3,
> +	SLPC_PLATFORM_SKU_MOBL = 4,
> +	SLPC_PLATFORM_SKU_DT = 5,
> +	SLPC_PLATFORM_SKU_UNKNOWN = 6,
> +};
> +
> +struct slpc_platform_info {
> +	union {
> +		u32 sku;  /**< SKU info */
> +		struct {
> +			u32 reserved:8;
> +			u32 fused_slice_count:8;
> +			u32 reserved1:16;
> +		};
> +	};
> +        union
> +	{
> +		u32 bitfield2;       /**< IA capability info*/
> +		struct {
> +			u32 max_p0_freq_bins:8;
> +			u32 p1_freq_bins:8;
> +			u32 pe_freq_bins:8;
> +			u32 pn_freq_bins:8;
> +		};
> +	};
> +	u32 reserved2[2];
> +} __packed;

I'm not a big fan of using C bitfields for interface definitions

can we switch to regular #defines and use FIELD_GET|PREP ?

> +
> +struct slpc_task_state_data {
> +	union {
> +		u32 bitfield1;
> +		struct {
> +			u32 gtperf_task_active:1;
> +			u32 gtperf_stall_possible:1;
> +			u32 gtperf_gaming_mode:1;
> +			u32 gtperf_target_fps:8;
> +			u32 dcc_task_active:1;
> +			u32 in_dcc:1;
> +			u32 in_dct:1;
> +			u32 freq_switch_active:1;
> +			u32 ibc_enabled:1;
> +			u32 ibc_active:1;
> +			u32 pg1_enabled:1;
> +			u32 pg1_active:1;
> +		};
> +	};
> +	union {
> +		u32 bitfield2;
> +		struct {
> +			u32 max_unslice_freq:8;
> +			u32 min_unslice_freq:8;
> +			u32 max_slice_freq:8;
> +			u32 min_slice_freq:8;
> +		};
> +	};
> +} __packed;
> +
> +struct slpc_shared_data {
> +	union {
> +		struct {
> +			/* Total size in bytes of this buffer. */
> +			u32 shared_data_size;
> +			u32 global_state;
> +			u32 display_data_addr;
> +		};

below all structs are named, this one not, why ?

> +		unsigned char reserved_header[SLPC_SHARE_DATA_SIZE_BYTE_HEADER];

this could be just "u8"

and I assume all these "reserved" are in fact padding, no ?

> +	};
> +
> +	union {
> +		struct slpc_platform_info platform_info;
> +		unsigned char reserved_platform[SLPC_SHARE_DATA_SIZE_BYTE_PLATFORM_INFO];
> +	};

maybe we can avoid these unions by declaring padding explicitly:

	struct slpc_platform_info platform_info;
	u8 platform_info_pad[SLPC_SHARE_DATA_SIZE_BYTE_PLATFORM_INFO -
	                     sizeof(struct slpc_platform_info)];

> +
> +	union {
> +		struct slpc_task_state_data task_state_data;
> +		unsigned char reserved_task_state[SLPC_SHARE_DATA_SIZE_BYTE_TASK_STATE];
> +	};
> +
> +	union {
> +		struct {
> +		u32 override_params_set_bits[SLPC_OVERRIDE_BITFIELD_SIZE];
> +		u32 override_params_values[SLPC_MAX_OVERRIDE_PARAMETERS];
> +		};
> +		unsigned char reserved_override_parameter[SLPC_SHARE_DATA_SIZE_BYTE_PARAM];
> +	};
> +
> +	unsigned char reserved_other[SLPC_SHARE_DATA_SIZE_BYTE_OTHER];
> +
> +	/* PAGE 2 (4096 bytes), mode based parameter will be removed soon */
> +	unsigned char reserved_mode_definition[4096];
> +} __packed;
> +
> +enum slpc_reset_flags {
> +	SLPC_RESET_FLAG_TDR_OCCURRED = (1 << 0)
> +};
> +
> +#define SLPC_EVENT_MAX_INPUT_ARGS  9
> +#define SLPC_EVENT_MAX_OUTPUT_ARGS 1
> +
> +union slpc_event_input_header {
> +	u32 value;
> +	struct {
> +		u32 num_args:8;
> +		u32 event_id:8;
> +	};
> +};

I guess earlier #define SLPC_EVENT is related to above
can we keep related definitions together ?

> +
> +struct slpc_event_input {
> +	u32 h2g_action_id;
> +	union slpc_event_input_header header;
> +	u32 args[SLPC_EVENT_MAX_INPUT_ARGS];
> +} __packed;

this looks like a attempt to define details of the
INTEL_GUC_ACTION_SLPC_REQUEST HXG request message.

so maybe it can be moved to abi/guc_actions_slpc_abi.h ?
best if you can define it in the same fashion as CTB registration one

Michal

> +
> +#endif
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 06/16] drm/i915/guc/slpc: Allocate, initialize and release slpc
  2021-07-10  1:20 ` [PATCH 06/16] drm/i915/guc/slpc: Allocate, initialize and release slpc Vinay Belgaumkar
@ 2021-07-10 16:05   ` Michal Wajdeczko
  2021-07-14  1:40     ` Belgaumkar, Vinay
  0 siblings, 1 reply; 49+ messages in thread
From: Michal Wajdeczko @ 2021-07-10 16:05 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel; +Cc: Sundaresan Sujaritha



On 10.07.2021 03:20, Vinay Belgaumkar wrote:
> Allocate data structures for SLPC and functions for
> initializing on host side.
> 
> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc.c      | 11 +++++++
>  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 36 ++++++++++++++++++++-
>  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 20 ++++++++++++
>  3 files changed, 66 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> index 9d61b2d54de4..82863a9bc8e8 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> @@ -336,6 +336,12 @@ int intel_guc_init(struct intel_guc *guc)
>  			goto err_ct;
>  	}
>  
> +	if (intel_guc_slpc_is_used(guc)) {
> +		ret = intel_guc_slpc_init(&guc->slpc);
> +		if (ret)
> +			goto err_submission;
> +	}
> +
>  	/* now that everything is perma-pinned, initialize the parameters */
>  	guc_init_params(guc);
>  
> @@ -346,6 +352,8 @@ int intel_guc_init(struct intel_guc *guc)
>  
>  	return 0;
>  
> +err_submission:
> +	intel_guc_submission_fini(guc);
>  err_ct:
>  	intel_guc_ct_fini(&guc->ct);
>  err_ads:
> @@ -368,6 +376,9 @@ void intel_guc_fini(struct intel_guc *guc)
>  
>  	i915_ggtt_disable_guc(gt->ggtt);
>  
> +	if (intel_guc_slpc_is_used(guc))
> +		intel_guc_slpc_fini(&guc->slpc);
> +
>  	if (intel_guc_submission_is_used(guc))
>  		intel_guc_submission_fini(guc);
>  
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> index c1f569d2300d..94e2f19951aa 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> @@ -4,11 +4,41 @@
>   * Copyright © 2020 Intel Corporation
>   */
>  
> +#include <asm/msr-index.h>

hmm, what exactly is needed from this header ?

> +
> +#include "gt/intel_gt.h"
> +#include "gt/intel_rps.h"
> +
> +#include "i915_drv.h"
>  #include "intel_guc_slpc.h"
> +#include "intel_pm.h"
> +
> +static inline struct intel_guc *slpc_to_guc(struct intel_guc_slpc *slpc)
> +{
> +	return container_of(slpc, struct intel_guc, slpc);
> +}
> +
> +static int slpc_shared_data_init(struct intel_guc_slpc *slpc)
> +{
> +	struct intel_guc *guc = slpc_to_guc(slpc);
> +	int err;
> +	u32 size = PAGE_ALIGN(sizeof(struct slpc_shared_data));

move err decl here

> +
> +	err = intel_guc_allocate_and_map_vma(guc, size, &slpc->vma, &slpc->vaddr);
> +	if (unlikely(err)) {
> +		DRM_ERROR("Failed to allocate slpc struct (err=%d)\n", err);

s/slpc/SLPC

and use drm_err instead
and you may also want to print error as %pe

> +		i915_vma_unpin_and_release(&slpc->vma, I915_VMA_RELEASE_MAP);

do you really need this ?

> +		return err;
> +	}
> +
> +	return err;
> +}
>  
>  int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
>  {
> -	return 0;
> +	GEM_BUG_ON(slpc->vma);
> +
> +	return slpc_shared_data_init(slpc);
>  }
>  
>  /*
> @@ -31,4 +61,8 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
>  
>  void intel_guc_slpc_fini(struct intel_guc_slpc *slpc)
>  {
> +	if (!slpc->vma)
> +		return;
> +
> +	i915_vma_unpin_and_release(&slpc->vma, I915_VMA_RELEASE_MAP);
>  }
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> index 98036459a1a3..a2643b904165 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> @@ -3,12 +3,32 @@
>   *
>   * Copyright © 2020 Intel Corporation
>   */
> +

should be fixed in earlier patch

>  #ifndef _INTEL_GUC_SLPC_H_
>  #define _INTEL_GUC_SLPC_H_
>  
> +#include <linux/mutex.h>
>  #include "intel_guc_slpc_fwif.h"
>  
>  struct intel_guc_slpc {
> +	/*Protects access to vma and SLPC actions */

hmm, missing mutex ;)

> +	struct i915_vma *vma;
> +	void *vaddr;

no need to be void, define it as ptr to slpc_shared_data

> +
> +	/* platform frequency limits */
> +	u32 min_freq;
> +	u32 rp0_freq;
> +	u32 rp1_freq;
> +
> +	/* frequency softlimits */
> +	u32 min_freq_softlimit;
> +	u32 max_freq_softlimit;
> +
> +	struct {
> +		u32 param_id;
> +		u32 param_value;
> +		u32 param_override;
> +	} debug;

can you add all these extra fields in patches which will need them?

Michal

>  };
>  
>  int intel_guc_slpc_init(struct intel_guc_slpc *slpc);
> 


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Intel-gfx] [PATCH 07/16] drm/i915/guc/slpc: Enable slpc and add related H2G events
  2021-07-10  1:20 ` [PATCH 07/16] drm/i915/guc/slpc: Enable slpc and add related H2G events Vinay Belgaumkar
@ 2021-07-10 17:37   ` Michal Wajdeczko
  2021-07-15  1:58     ` Belgaumkar, Vinay
  0 siblings, 1 reply; 49+ messages in thread
From: Michal Wajdeczko @ 2021-07-10 17:37 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel



On 10.07.2021 03:20, Vinay Belgaumkar wrote:
> Add methods for interacting with guc for enabling SLPC. Enable
> SLPC after guc submission has been established. GuC load will

s/guc/GuC

> fail if SLPC cannot be successfully initialized. Add various
> helper methods to set/unset the parameters for SLPC. They can
> be set using h2g calls or directly setting bits in the shared

/h2g/H2G

> data structure.
> 
> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c   | 221 ++++++++++++++++++
>  .../gpu/drm/i915/gt/uc/intel_guc_submission.c |   4 -
>  drivers/gpu/drm/i915/gt/uc/intel_uc.c         |  10 +
>  3 files changed, 231 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> index 94e2f19951aa..e579408d1c19 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> @@ -18,6 +18,61 @@ static inline struct intel_guc *slpc_to_guc(struct intel_guc_slpc *slpc)
>  	return container_of(slpc, struct intel_guc, slpc);
>  }
>  
> +static inline struct intel_gt *slpc_to_gt(struct intel_guc_slpc *slpc)
> +{
> +	return guc_to_gt(slpc_to_guc(slpc));
> +}
> +
> +static inline struct drm_i915_private *slpc_to_i915(struct intel_guc_slpc *slpc)
> +{
> +	return (slpc_to_gt(slpc))->i915;
> +}
> +
> +static void slpc_mem_set_param(struct slpc_shared_data *data,
> +				u32 id, u32 value)
> +{
> +	GEM_BUG_ON(id >= SLPC_MAX_OVERRIDE_PARAMETERS);
> +	/* When the flag bit is set, corresponding value will be read
> +	 * and applied by slpc.

fix format of multi-line comment
s/slpc/SLPC

> +	 */
> +	data->override_params_set_bits[id >> 5] |= (1 << (id % 32));

use __set_bit instead

> +	data->override_params_values[id] = value;
> +}
> +
> +static void slpc_mem_unset_param(struct slpc_shared_data *data,
> +				 u32 id)
> +{
> +	GEM_BUG_ON(id >= SLPC_MAX_OVERRIDE_PARAMETERS);
> +	/* When the flag bit is unset, corresponding value will not be
> +	 * read by slpc.
> +	 */
> +	data->override_params_set_bits[id >> 5] &= (~(1 << (id % 32)));

same here

> +	data->override_params_values[id] = 0;
> +}
> +
> +static void slpc_mem_task_control(struct slpc_shared_data *data,
> +				 u64 val, u32 enable_id, u32 disable_id)

hmm, u64 to pass simple tri-state flag ?

> +{
> +	/* Enabling a param involves setting the enable_id
> +	 * to 1 and disable_id to 0. Setting it to default
> +	 * will unset both enable and disable ids and let
> +	 * slpc choose it's default values.

fix format + s/slpc/SLPC

> +	 */
> +	if (val == SLPC_PARAM_TASK_DEFAULT) {
> +		/* set default */
> +		slpc_mem_unset_param(data, enable_id);
> +		slpc_mem_unset_param(data, disable_id);
> +	} else if (val == SLPC_PARAM_TASK_ENABLED) {
> +		/* set enable */
> +		slpc_mem_set_param(data, enable_id, 1);
> +		slpc_mem_set_param(data, disable_id, 0);
> +	} else if (val == SLPC_PARAM_TASK_DISABLED) {
> +		/* set disable */
> +		slpc_mem_set_param(data, disable_id, 1);
> +		slpc_mem_set_param(data, enable_id, 0);
> +	}

maybe instead of SLPC_PARAM_TASK_* flags (that btw were confusing me
earlier) you can define 3x small helpers:

static void slpc_mem_set_default(data, enable_id, disable_id);
static void slpc_mem_set_enabled(data, enable_id, disable_id);
static void slpc_mem_set_disabled(data, enable_id, disable_id);


> +}
> +
>  static int slpc_shared_data_init(struct intel_guc_slpc *slpc)
>  {
>  	struct intel_guc *guc = slpc_to_guc(slpc);
> @@ -34,6 +89,128 @@ static int slpc_shared_data_init(struct intel_guc_slpc *slpc)
>  	return err;
>  }
>  
> +/*
> + * Send SLPC event to guc
> + *
> + */
> +static int slpc_send(struct intel_guc_slpc *slpc,
> +			struct slpc_event_input *input,
> +			u32 in_len)
> +{
> +	struct intel_guc *guc = slpc_to_guc(slpc);
> +	u32 *action;
> +
> +	action = (u32 *)input;
> +	action[0] = INTEL_GUC_ACTION_SLPC_REQUEST;

why not just updating input->h2g_action_id ?

> +
> +	return intel_guc_send(guc, action, in_len);
> +}
> +
> +static bool slpc_running(struct intel_guc_slpc *slpc)
> +{
> +	struct slpc_shared_data *data;
> +	u32 slpc_global_state;
> +
> +	GEM_BUG_ON(!slpc->vma);
> +
> +	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));

do you really need to flush all 8K of shared data?
it looks that you only need single u32

> +	data = slpc->vaddr;
> +
> +	slpc_global_state = data->global_state;
> +
> +	return (data->global_state == SLPC_GLOBAL_STATE_RUNNING);
> +}
> +
> +static int host2guc_slpc_query_task_state(struct intel_guc_slpc *slpc)
> +{
> +	struct intel_guc *guc = slpc_to_guc(slpc);
> +	u32 shared_data_gtt_offset = intel_guc_ggtt_offset(guc, slpc->vma);
> +	struct slpc_event_input data = {0};
> +
> +	data.header.value = SLPC_EVENT(SLPC_EVENT_QUERY_TASK_STATE, 2);

you defined header.num_args and header.event_id, don't want to use them?

> +	data.args[0] = shared_data_gtt_offset;
> +	data.args[1] = 0;
> +
> +	return slpc_send(slpc, &data, 4);

magic 4

> +}
> +
> +static int slpc_read_task_state(struct intel_guc_slpc *slpc)
> +{
> +	return host2guc_slpc_query_task_state(slpc);
> +}

hmm, all this looks complicated more than needed, why not just:

static int guc_action_slpc_query(struct intel_guc *guc, u32 offset)
{
	u32 request[] = {
		INTEL_GUC_ACTION_SLPC_REQUEST,
		SLPC_EVENT(SLPC_EVENT_QUERY_TASK_STATE, 2),
		offset,
		0,
	};
	int err;

	return intel_guc_send(guc, request, ARRAY_SIZE(request));
}

static int slpc_query_task_state(struct intel_guc_slpc *slpc)
{
	struct intel_guc *guc = slpc_to_guc(slpc);
	u32 offset = intel_guc_ggtt_offset(guc, slpc->vma);

	return guc_action_slpc_query(guc, offset);
}

btw, there is little magic in H2G data, as only event enums were defined
in slpc_fwif.h (or slpc_abi.h) but it looks that len and format of args
depends on the actual event used

> +
> +static const char *slpc_state_stringify(enum slpc_global_state state)
> +{
> +	const char *str = NULL;
> +
> +	switch (state) {
> +	case SLPC_GLOBAL_STATE_NOT_RUNNING:
> +		str = "not running";
> +		break;
> +	case SLPC_GLOBAL_STATE_INITIALIZING:
> +		str = "initializing";
> +		break;
> +	case SLPC_GLOBAL_STATE_RESETTING:
> +		str = "resetting";
> +		break;
> +	case SLPC_GLOBAL_STATE_RUNNING:
> +		str = "running";
> +		break;
> +	case SLPC_GLOBAL_STATE_SHUTTING_DOWN:
> +		str = "shutting down";
> +		break;
> +	case SLPC_GLOBAL_STATE_ERROR:
> +		str = "error";
> +		break;
> +	default:
> +		str = "unknown";
> +		break;
> +	}
> +
> +	return str;
> +}
> +
> +static const char *get_slpc_state(struct intel_guc_slpc *slpc)

lot of duplicated code with slpc_running()

maybe there should be:
	u32 slpc_get_state(slpc);
	bool slpc_is_running(slpc);
	const char *slpc_state_string(slpc);


> +{
> +	struct slpc_shared_data *data;
> +	u32 slpc_global_state;
> +
> +	GEM_BUG_ON(!slpc->vma);
> +
> +	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));
> +	data = slpc->vaddr;
> +
> +	slpc_global_state = data->global_state;
> +
> +	return slpc_state_stringify(slpc_global_state);
> +}
> +
> +static int host2guc_slpc_reset(struct intel_guc_slpc *slpc)
> +{
> +	struct intel_guc *guc = slpc_to_guc(slpc);
> +	u32 shared_data_gtt_offset = intel_guc_ggtt_offset(guc, slpc->vma);
> +	struct slpc_event_input data = {0};
> +	int ret;
> +
> +	data.header.value = SLPC_EVENT(SLPC_EVENT_RESET, 2);
> +	data.args[0] = shared_data_gtt_offset;
> +	data.args[1] = 0;
> +
> +	/* TODO: Hardcoded 4 needs define */
> +	ret = slpc_send(slpc, &data, 4);
> +
> +	if (!ret) {
> +		/* TODO: How long to Wait until SLPC is running */

do we know state transitions ?
maybe there is no point in waiting for RUNNING if it is in ERROR or
SHUTTING_DOWN ?

> +		if (wait_for(slpc_running(slpc), 5)) {

magic 5

> +			DRM_ERROR("SLPC not enabled! State = %s\n",

use drm_err

> +				  get_slpc_state(slpc));
> +			return -EIO;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
>  int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
>  {
>  	GEM_BUG_ON(slpc->vma);
> @@ -56,6 +233,50 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
>   */
>  int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
>  {
> +	struct drm_i915_private *i915 = slpc_to_i915(slpc);
> +	struct slpc_shared_data *data;
> +	int ret;
> +
> +	GEM_BUG_ON(!slpc->vma);
> +
> +	memset(slpc->vaddr, 0, sizeof(struct slpc_shared_data));
> +
> +	data = slpc->vaddr;
> +	data->shared_data_size = sizeof(struct slpc_shared_data);
> +
> +	/* Enable only GTPERF task, Disable others */
> +	slpc_mem_task_control(data, SLPC_PARAM_TASK_ENABLED,
> +				SLPC_PARAM_TASK_ENABLE_GTPERF,
> +				SLPC_PARAM_TASK_DISABLE_GTPERF);
> +
> +	slpc_mem_task_control(data, SLPC_PARAM_TASK_DISABLED,
> +				SLPC_PARAM_TASK_ENABLE_BALANCER,
> +				SLPC_PARAM_TASK_DISABLE_BALANCER);
> +
> +	slpc_mem_task_control(data, SLPC_PARAM_TASK_DISABLED,
> +				SLPC_PARAM_TASK_ENABLE_DCC,
> +				SLPC_PARAM_TASK_DISABLE_DCC);
> +
> +	ret = host2guc_slpc_reset(slpc);
> +	if (ret) {
> +		drm_err(&i915->drm, "SLPC Reset event returned %d", ret);

you may want to print error as %pe
missing \n

> +		return -EIO;
> +	}
> +
> +	DRM_INFO("SLPC state: %s\n", get_slpc_state(slpc));

use drm_info

> +
> +	if (slpc_read_task_state(slpc))
> +		drm_err(&i915->drm, "Unable to read task state data");

missing \n

> +
> +	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));
> +
> +	/* min and max frequency limits being used by SLPC */
> +	drm_info(&i915->drm, "SLPC min freq: %u Mhz, max is %u Mhz",

missing \n

> +			DIV_ROUND_CLOSEST(data->task_state_data.min_unslice_freq *
> +				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER),
> +			DIV_ROUND_CLOSEST(data->task_state_data.max_unslice_freq *
> +				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER));

this info/code seems to be duplicated in patch 10/16
maybe just call intel_guc_slpc_info() here once available ?

> +
>  	return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
> index e2644a05f298..3e76d4d5f7bb 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
> @@ -2321,10 +2321,6 @@ void intel_guc_submission_enable(struct intel_guc *guc)
>  
>  void intel_guc_submission_disable(struct intel_guc *guc)
>  {
> -	struct intel_gt *gt = guc_to_gt(guc);
> -
> -	GEM_BUG_ON(gt->awake); /* GT should be parked first */

if not mistake, can you explain why it was removed ?

> -
>  	/* Note: By the time we're here, GuC may have already been reset */
>  }
>  
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
> index dca5f6d0641b..7b6c767d3eb0 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
> @@ -501,6 +501,14 @@ static int __uc_init_hw(struct intel_uc *uc)
>  	if (intel_uc_uses_guc_submission(uc))
>  		intel_guc_submission_enable(guc);
>  
> +	if (intel_uc_uses_guc_slpc(uc)) {
> +		ret = intel_guc_slpc_enable(&guc->slpc);
> +		if (ret)
> +			goto err_submission;
> +		drm_info(&i915->drm, "GuC SLPC %s\n",
> +			 enableddisabled(intel_uc_uses_guc_slpc(uc)));

move this drm_info after below GuC report and/or modify to have:

"GuC firmware path.bin version 1.0 loaded:yes"
"GuC submission:enabled"
"GuC SLPC:enabled"
"HuC firmware path.bin version 1.0 authenticated:yes"

Michal

> +	}
> +
>  	drm_info(&i915->drm, "%s firmware %s version %u.%u %s:%s\n",
>  		 intel_uc_fw_type_repr(INTEL_UC_FW_TYPE_GUC), guc->fw.path,
>  		 guc->fw.major_ver_found, guc->fw.minor_ver_found,
> @@ -521,6 +529,8 @@ static int __uc_init_hw(struct intel_uc *uc)
>  	/*
>  	 * We've failed to load the firmware :(
>  	 */
> +err_submission:
> +	intel_guc_submission_disable(guc);
>  err_log_capture:
>  	__uc_capture_load_err_log(uc);
>  err_out:
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 08/16] drm/i915/guc/slpc: Add methods to set min/max frequency
  2021-07-10  1:20 ` [PATCH 08/16] drm/i915/guc/slpc: Add methods to set min/max frequency Vinay Belgaumkar
  2021-07-10  3:07   ` kernel test robot
  2021-07-10  5:17   ` kernel test robot
@ 2021-07-10 17:47   ` Michal Wajdeczko
  2021-07-16 18:00     ` Belgaumkar, Vinay
  2 siblings, 1 reply; 49+ messages in thread
From: Michal Wajdeczko @ 2021-07-10 17:47 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel; +Cc: Sundaresan Sujaritha



On 10.07.2021 03:20, Vinay Belgaumkar wrote:
> Add param set h2g helpers to set the min and max frequencies
> for use by SLPC.
> 
> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 94 +++++++++++++++++++++
>  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h |  2 +
>  2 files changed, 96 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> index e579408d1c19..19cb26479942 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> @@ -106,6 +106,19 @@ static int slpc_send(struct intel_guc_slpc *slpc,
>  	return intel_guc_send(guc, action, in_len);
>  }
>  
> +static int host2guc_slpc_set_param(struct intel_guc_slpc *slpc,
> +				   u32 id, u32 value)
> +{
> +	struct slpc_event_input data = {0};
> +
> +	data.header.value = SLPC_EVENT(SLPC_EVENT_PARAMETER_SET, 2);
> +	data.args[0] = id;
> +	data.args[1] = value;
> +
> +	return slpc_send(slpc, &data, 4);

as suggested before, use of explicit function like:

static int guc_action_slpc_param(guc, u32 id, u32 value)
{
	u32 request[] = {
		INTEL_GUC_ACTION_SLPC_REQUEST,
		SLPC_EVENT(SLPC_EVENT_PARAMETER_SET, 2),
		id,
		value,
	};

	return intel_guc_send(guc, request, ARRAY_SIZE(request));
}

will be simpler/cleaner

> +}
> +
> +
>  static bool slpc_running(struct intel_guc_slpc *slpc)
>  {
>  	struct slpc_shared_data *data;
> @@ -134,6 +147,19 @@ static int host2guc_slpc_query_task_state(struct intel_guc_slpc *slpc)
>  	return slpc_send(slpc, &data, 4);
>  }
>  
> +static int slpc_set_param(struct intel_guc_slpc *slpc, u32 id, u32 value)
> +{
> +	struct drm_i915_private *i915 = slpc_to_i915(slpc);
> +	GEM_BUG_ON(id >= SLPC_MAX_PARAM);
> +
> +	if (host2guc_slpc_set_param(slpc, id, value)) {
> +		drm_err(&i915->drm, "Unable to set param %x", id);

missing \n
what about printing value to be set ?
what about printing send error %pe ?

> +		return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
>  static int slpc_read_task_state(struct intel_guc_slpc *slpc)
>  {
>  	return host2guc_slpc_query_task_state(slpc);
> @@ -218,6 +244,74 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
>  	return slpc_shared_data_init(slpc);
>  }
>  
> +/**
> + * intel_guc_slpc_max_freq_set() - Set max frequency limit for SLPC.
> + * @slpc: pointer to intel_guc_slpc.
> + * @val: encoded frequency

what's the encoding ?

> + *
> + * This function will invoke GuC SLPC action to update the max frequency
> + * limit for slice and unslice.
> + *
> + * Return: 0 on success, non-zero error code on failure.
> + */
> +int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val)
> +{
> +	int ret;
> +	struct drm_i915_private *i915 = slpc_to_i915(slpc);
> +	intel_wakeref_t wakeref;
> +
> +	wakeref = intel_runtime_pm_get(&i915->runtime_pm);

use can use with_intel_runtime_pm(rpm, wakeref)

> +
> +	ret = slpc_set_param(slpc,
> +		       SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ,
> +		       val);
> +
> +	if (ret) {
> +		drm_err(&i915->drm,
> +			"Set max frequency unslice returned %d", ret);

missing \n
print error with %pe
but slpc_set_param returns only -EIO ;(

> +		ret = -EIO;
> +		goto done;
> +	}
> +
> +done:
> +	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
> +	return ret;
> +}
> +
> +/**
> + * intel_guc_slpc_min_freq_set() - Set min frequency limit for SLPC.
> + * @slpc: pointer to intel_guc_slpc.
> + * @val: encoded frequency
> + *
> + * This function will invoke GuC SLPC action to update the min frequency
> + * limit.
> + *
> + * Return: 0 on success, non-zero error code on failure.
> + */
> +int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val)
> +{
> +	int ret;
> +	struct intel_guc *guc = slpc_to_guc(slpc);
> +	struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
> +	intel_wakeref_t wakeref;
> +
> +	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
> +
> +	ret = slpc_set_param(slpc,
> +		       SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
> +		       val);
> +	if (ret) {
> +		drm_err(&i915->drm,
> +			"Set min frequency for unslice returned %d", ret);

as above

Michal

> +		ret = -EIO;
> +		goto done;
> +	}
> +
> +done:
> +	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
> +	return ret;
> +}
> +
>  /*
>   * intel_guc_slpc_enable() - Start SLPC
>   * @slpc: pointer to intel_guc_slpc.
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> index a2643b904165..a473e1ea7c10 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> @@ -34,5 +34,7 @@ struct intel_guc_slpc {
>  int intel_guc_slpc_init(struct intel_guc_slpc *slpc);
>  int intel_guc_slpc_enable(struct intel_guc_slpc *slpc);
>  void intel_guc_slpc_fini(struct intel_guc_slpc *slpc);
> +int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val);
> +int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val);
>  
>  #endif
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 09/16] drm/i915/guc/slpc: Add get max/min freq hooks
  2021-07-10  1:20 ` [PATCH 09/16] drm/i915/guc/slpc: Add get max/min freq hooks Vinay Belgaumkar
@ 2021-07-10 17:52   ` Michal Wajdeczko
  2021-07-20 22:08     ` Belgaumkar, Vinay
  0 siblings, 1 reply; 49+ messages in thread
From: Michal Wajdeczko @ 2021-07-10 17:52 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel; +Cc: Sundaresan Sujaritha



On 10.07.2021 03:20, Vinay Belgaumkar wrote:
> Add helpers to read the min/max frequency being used
> by SLPC. This is done by send a h2g command which forces

s/h2g/H2G

> SLPC to update the shared data struct which can then be
> read.
> 
> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 58 +++++++++++++++++++++
>  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h |  2 +
>  2 files changed, 60 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> index 19cb26479942..98a283d31734 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> @@ -278,6 +278,35 @@ int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val)
>  	return ret;
>  }
>  
> +int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val)
> +{
> +	struct slpc_shared_data *data;
> +	intel_wakeref_t wakeref;
> +	struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915;
> +	int ret = 0;
> +
> +	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
> +
> +	/* Force GuC to update task data */
> +	if (slpc_read_task_state(slpc)) {
> +		DRM_ERROR("Unable to update task data");

use drm_err
missing \n
maybe this message could be moved to slpc_read_task_state ?

> +		ret = -EIO;
> +		goto done;
> +	}
> +
> +	GEM_BUG_ON(!slpc->vma);
> +
> +	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));

maybe this can also be part of slpc_read_task_state ?

> +	data = slpc->vaddr;
> +
> +	*val = DIV_ROUND_CLOSEST(data->task_state_data.max_unslice_freq *
> +				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER);
> +
> +done:
> +	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
> +	return ret;
> +}
> +
>  /**
>   * intel_guc_slpc_min_freq_set() - Set min frequency limit for SLPC.
>   * @slpc: pointer to intel_guc_slpc.
> @@ -312,6 +341,35 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val)
>  	return ret;
>  }
>  
> +int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val)

missing kernel-doc (above intel_guc_slpc_min_freq_set has one)

> +{
> +	struct slpc_shared_data *data;
> +	intel_wakeref_t wakeref;
> +	struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915;
> +	int ret = 0;
> +
> +	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
> +
> +	/* Force GuC to update task data */
> +	if (slpc_read_task_state(slpc)) {
> +		DRM_ERROR("Unable to update task data");

see above

> +		ret = -EIO;
> +		goto done;
> +	}
> +
> +	GEM_BUG_ON(!slpc->vma);
> +
> +	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));

see above

Michal

> +	data = slpc->vaddr;
> +
> +	*val = DIV_ROUND_CLOSEST(data->task_state_data.min_unslice_freq *
> +				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER);
> +
> +done:
> +	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
> +	return ret;
> +}
> +
>  /*
>   * intel_guc_slpc_enable() - Start SLPC
>   * @slpc: pointer to intel_guc_slpc.
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> index a473e1ea7c10..2cb830cdacb5 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> @@ -36,5 +36,7 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc);
>  void intel_guc_slpc_fini(struct intel_guc_slpc *slpc);
>  int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val);
>  int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val);
> +int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val);
> +int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val);
>  
>  #endif
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 10/16] drm/i915/guc/slpc: Add debugfs for slpc info
  2021-07-10  1:20 ` [PATCH 10/16] drm/i915/guc/slpc: Add debugfs for slpc info Vinay Belgaumkar
@ 2021-07-10 18:08   ` Michal Wajdeczko
  2021-07-20 23:00     ` Belgaumkar, Vinay
  0 siblings, 1 reply; 49+ messages in thread
From: Michal Wajdeczko @ 2021-07-10 18:08 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel; +Cc: Sundaresan Sujaritha



On 10.07.2021 03:20, Vinay Belgaumkar wrote:
> This prints out relevant SLPC info from the SLPC shared structure.
> 
> We will send a h2g message which forces SLPC to update the
> shared data structure with latest information before reading it.
> 
> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
> ---
>  .../gpu/drm/i915/gt/uc/intel_guc_debugfs.c    | 16 ++++++
>  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c   | 53 +++++++++++++++++++
>  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h   |  3 ++
>  3 files changed, 72 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
> index 9a03ff56e654..bef749e54601 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
> @@ -12,6 +12,7 @@
>  #include "gt/uc/intel_guc_ct.h"
>  #include "gt/uc/intel_guc_ads.h"
>  #include "gt/uc/intel_guc_submission.h"
> +#include "gt/uc/intel_guc_slpc.h"
>  
>  static int guc_info_show(struct seq_file *m, void *data)
>  {
> @@ -50,11 +51,26 @@ static int guc_registered_contexts_show(struct seq_file *m, void *data)
>  }
>  DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_registered_contexts);
>  
> +static int guc_slpc_info_show(struct seq_file *m, void *unused)
> +{
> +	struct intel_guc *guc = m->private;
> +	struct intel_guc_slpc *slpc = &guc->slpc;
> +	struct drm_printer p = drm_seq_file_printer(m);
> +
> +	if (!intel_guc_slpc_is_used(guc))
> +		return -ENODEV;
> +
> +	return intel_guc_slpc_info(slpc, &p);
> +}
> +

other entries don't have empty line here

> +DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_slpc_info);
> +
>  void intel_guc_debugfs_register(struct intel_guc *guc, struct dentry *root)
>  {
>  	static const struct debugfs_gt_file files[] = {
>  		{ "guc_info", &guc_info_fops, NULL },
>  		{ "guc_registered_contexts", &guc_registered_contexts_fops, NULL },
> +		{ "guc_slpc_info", &guc_slpc_info_fops, NULL},

IIRC last field is "eval" where maybe you could add your own to check if
intel_guc_slpc_is_used() to avoid exposing this info if N/A

>  	};
>  
>  	if (!intel_guc_is_supported(guc))
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> index 98a283d31734..d179ba14ece6 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> @@ -432,6 +432,59 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
>  	return 0;
>  }
>  
> +int intel_guc_slpc_info(struct intel_guc_slpc *slpc, struct drm_printer *p)
> +{
> +	struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915;
> +	struct slpc_shared_data *data;
> +	struct slpc_platform_info *platform_info;
> +	struct slpc_task_state_data *task_state_data;
> +	intel_wakeref_t wakeref;
> +	int ret = 0;
> +
> +	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
> +
> +	if (slpc_read_task_state(slpc)) {
> +		ret = -EIO;
> +		goto done;
> +	}
> +
> +	GEM_BUG_ON(!slpc->vma);
> +
> +	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));

likely will go away if integrated into slpc_read_task_state

> +	data = slpc->vaddr;
> +
> +	platform_info = &data->platform_info;

is this used ?

> +	task_state_data = &data->task_state_data;

as it looks that you treat these sections separately, then maybe it
would be cleaner to have:

static void print_global_data(*global_data, *p) {}
static void print_platform_info(*platform_info, *p) {}
static void print_task_state_data(*task_state_data, *p) {}

> +
> +	drm_printf(p, "SLPC state: %s\n", slpc_state_stringify(data->global_state));
> +	drm_printf(p, "\tgtperf task active: %d\n",
> +			task_state_data->gtperf_task_active);
> +	drm_printf(p, "\tdcc task active: %d\n",
> +				task_state_data->dcc_task_active);
> +	drm_printf(p, "\tin dcc: %d\n",
> +				task_state_data->in_dcc);
> +	drm_printf(p, "\tfreq switch active: %d\n",
> +				task_state_data->freq_switch_active);
> +	drm_printf(p, "\tibc enabled: %d\n",
> +				task_state_data->ibc_enabled);
> +	drm_printf(p, "\tibc active: %d\n",
> +				task_state_data->ibc_active);
> +	drm_printf(p, "\tpg1 enabled: %s\n",
> +				yesno(task_state_data->pg1_enabled));
> +	drm_printf(p, "\tpg1 active: %s\n",
> +				yesno(task_state_data->pg1_active));
> +	drm_printf(p, "\tmax freq: %dMHz\n",
> +				DIV_ROUND_CLOSEST(data->task_state_data.max_unslice_freq *
> +				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER));
> +	drm_printf(p, "\tmin freq: %dMHz\n",
> +				DIV_ROUND_CLOSEST(data->task_state_data.min_unslice_freq *
> +				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER));

you defined task_state_data but in above 2 you're accessing it from data

Michal

> +
> +done:
> +	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
> +	return ret;
> +}
> +
>  void intel_guc_slpc_fini(struct intel_guc_slpc *slpc)
>  {
>  	if (!slpc->vma)
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> index 2cb830cdacb5..cd12c5f19f4b 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
> @@ -10,6 +10,8 @@
>  #include <linux/mutex.h>
>  #include "intel_guc_slpc_fwif.h"
>  
> +struct drm_printer;
> +
>  struct intel_guc_slpc {
>  	/*Protects access to vma and SLPC actions */
>  	struct i915_vma *vma;
> @@ -38,5 +40,6 @@ int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val);
>  int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val);
>  int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val);
>  int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val);
> +int intel_guc_slpc_info(struct intel_guc_slpc *slpc, struct drm_printer *p);
>  
>  #endif
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Intel-gfx] [PATCH 12/16] drm/i915/guc/slpc: Cache platform frequency limits for slpc
  2021-07-10  1:20 ` [PATCH 12/16] drm/i915/guc/slpc: Cache platform frequency limits for slpc Vinay Belgaumkar
@ 2021-07-10 18:15   ` Michal Wajdeczko
  2021-07-17 19:30     ` Belgaumkar, Vinay
  2021-07-20 23:05     ` Belgaumkar, Vinay
  0 siblings, 2 replies; 49+ messages in thread
From: Michal Wajdeczko @ 2021-07-10 18:15 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel



On 10.07.2021 03:20, Vinay Belgaumkar wrote:
> Cache rp0, rp1 and rpn platform limits into slpc structure
> for range checking while setting min/max frequencies.
> 
> Also add "soft" limits which keep track of frequency changes
> made from userland. These are initially set to platform min
> and max.
> 
> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 41 +++++++++++++++++++++
>  1 file changed, 41 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> index d32274cd1db7..6e978f27b7a6 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> @@ -86,6 +86,9 @@ static int slpc_shared_data_init(struct intel_guc_slpc *slpc)
>  		return err;
>  	}
>  
> +	slpc->max_freq_softlimit = 0;
> +	slpc->min_freq_softlimit = 0;

as mentioned earlier, now it is time to introduce these fields in .h

> +
>  	return err;
>  }
>  
> @@ -384,6 +387,29 @@ void intel_guc_pm_intrmsk_enable(struct intel_gt *gt)
>  			   GEN6_PMINTRMSK, pm_intrmsk_mbz, 0);
>  }
>  
> +static int intel_guc_slpc_set_softlimits(struct intel_guc_slpc *slpc)
> +{
> +	int ret = 0;
> +
> +	/* Softlimits are initially equivalent to platform limits
> +	 * unless they have deviated from defaults, in which case,
> +	 * we retain the values and set min/max accordingly.
> +	 */
> +	if (!slpc->max_freq_softlimit)
> +		slpc->max_freq_softlimit = slpc->rp0_freq;
> +	else if (slpc->max_freq_softlimit != slpc->rp0_freq)
> +		ret = intel_guc_slpc_set_max_freq(slpc,
> +					slpc->max_freq_softlimit);
> +
> +	if (!slpc->min_freq_softlimit)
> +		slpc->min_freq_softlimit = slpc->min_freq;
> +	else if (slpc->min_freq_softlimit != slpc->min_freq)
> +		ret = intel_guc_slpc_set_min_freq(slpc,
> +					slpc->min_freq_softlimit);
> +
> +	return ret;
> +}
> +
>  /*
>   * intel_guc_slpc_enable() - Start SLPC
>   * @slpc: pointer to intel_guc_slpc.
> @@ -402,6 +428,7 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
>  	struct drm_i915_private *i915 = slpc_to_i915(slpc);
>  	struct slpc_shared_data *data;
>  	int ret;
> +	u32 rp_state_cap;

move up to keep "ret" last

>  
>  	GEM_BUG_ON(!slpc->vma);
>  
> @@ -445,6 +472,20 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
>  			DIV_ROUND_CLOSEST(data->task_state_data.max_unslice_freq *
>  				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER));
>  
> +	rp_state_cap = intel_uncore_read(i915->gt.uncore, GEN6_RP_STATE_CAP);
> +
> +	slpc->rp0_freq = ((rp_state_cap >> 0) & 0xff) * GT_FREQUENCY_MULTIPLIER;
> +	slpc->min_freq = ((rp_state_cap >> 16) & 0xff) * GT_FREQUENCY_MULTIPLIER;
> +	slpc->rp1_freq = ((rp_state_cap >> 8) & 0xff) * GT_FREQUENCY_MULTIPLIER;

we should have definitions for these bits and then we should be able to
use REG_FIELD_GET

> +
> +	if (intel_guc_slpc_set_softlimits(slpc))
> +		drm_err(&i915->drm, "Unable to set softlimits");

missing \n
maybe we can also print error ?

> +
> +	drm_info(&i915->drm,
> +		 "Platform fused frequency values -  min: %u Mhz, max: %u Mhz",

missing \n
double space before 'min'

Michal

> +		 slpc->min_freq,
> +		 slpc->rp0_freq);
> +
>  	return 0;
>  }
>  
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc
  2021-07-10  1:20 ` [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc Vinay Belgaumkar
                     ` (3 preceding siblings ...)
  2021-07-10 13:54   ` [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc kernel test robot
@ 2021-07-10 18:20   ` Michal Wajdeczko
  2021-07-20 23:38     ` Belgaumkar, Vinay
  4 siblings, 1 reply; 49+ messages in thread
From: Michal Wajdeczko @ 2021-07-10 18:20 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel
  Cc: Tvrtko Ursulin, Sujaritha Sundaresan



On 10.07.2021 03:20, Vinay Belgaumkar wrote:
> Update the get/set min/max freq hooks to work for
> slpc case as well. Consolidate helpers for requested/min/max
> frequency get/set to intel_rps where the proper action can
> be taken depending on whether slpc is enabled.

2x s/slpc/SLPC

> 
> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> Signed-off-by: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
> ---
>  drivers/gpu/drm/i915/gt/intel_rps.c | 135 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/gt/intel_rps.h |   5 ++
>  drivers/gpu/drm/i915/i915_pmu.c     |   2 +-
>  drivers/gpu/drm/i915/i915_reg.h     |   2 +
>  drivers/gpu/drm/i915/i915_sysfs.c   |  71 +++------------
>  5 files changed, 154 insertions(+), 61 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c
> index e858eeb2c59d..88ffc5d90730 100644
> --- a/drivers/gpu/drm/i915/gt/intel_rps.c
> +++ b/drivers/gpu/drm/i915/gt/intel_rps.c
> @@ -37,6 +37,12 @@ static struct intel_uncore *rps_to_uncore(struct intel_rps *rps)
>  	return rps_to_gt(rps)->uncore;
>  }
>  
> +static struct intel_guc_slpc *rps_to_slpc(struct intel_rps *rps)
> +{
> +	struct intel_gt *gt = rps_to_gt(rps);
> +	return &gt->uc.guc.slpc;

either add empty line between decl/code or make it one-liner

> +}
> +
>  static bool rps_uses_slpc(struct intel_rps *rps)
>  {
>  	struct intel_gt *gt = rps_to_gt(rps);
> @@ -1960,6 +1966,135 @@ u32 intel_rps_read_actual_frequency(struct intel_rps *rps)
>  	return freq;
>  }
>  
> +u32 intel_rps_read_punit_req(struct intel_rps *rps)
> +{
> +	struct intel_uncore *uncore = rps_to_uncore(rps);
> +

drop empty line

> +	u32 pureq = intel_uncore_read(uncore, GEN6_RPNSWREQ);
> +
> +	return pureq;
> +}
> +
> +u32 intel_rps_get_req(struct intel_rps *rps, u32 pureq)
> +{
> +	u32 req = pureq >> GEN9_SW_REQ_UNSLICE_RATIO_SHIFT;
> +
> +	return req;
> +}
> +
> +u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps)
> +{
> +	u32 freq = intel_rps_get_req(rps, intel_rps_read_punit_req(rps));
> +
> +	return intel_gpu_freq(rps, freq);
> +}
> +
> +u32 intel_rps_get_requested_frequency(struct intel_rps *rps)
> +{
> +	if (rps_uses_slpc(rps))
> +		return intel_rps_read_punit_req_frequency(rps);
> +	else
> +		return intel_gpu_freq(rps, rps->cur_freq);
> +}
> +
> +u32 intel_rps_get_max_frequency(struct intel_rps *rps)
> +{
> +	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
> +
> +	if (rps_uses_slpc(rps))
> +		return slpc->max_freq_softlimit;
> +	else
> +		return intel_gpu_freq(rps, rps->max_freq_softlimit);
> +}
> +
> +int intel_rps_set_max_frequency(struct intel_rps *rps, u32 val)
> +{
> +	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
> +	int ret;
> +
> +	if (rps_uses_slpc(rps))
> +		return intel_guc_slpc_set_max_freq(slpc, val);
> +
> +	mutex_lock(&rps->lock);
> +
> +	val = intel_freq_opcode(rps, val);
> +	if (val < rps->min_freq ||
> +	    val > rps->max_freq ||
> +	    val < rps->min_freq_softlimit) {
> +		ret = -EINVAL;
> +		goto unlock;
> +	}
> +
> +	if (val > rps->rp0_freq)
> +		DRM_DEBUG("User requested overclocking to %d\n",

use drm_dbg

Michal

> +			  intel_gpu_freq(rps, val));
> +
> +	rps->max_freq_softlimit = val;
> +
> +	val = clamp_t(int, rps->cur_freq,
> +		      rps->min_freq_softlimit,
> +		      rps->max_freq_softlimit);
> +
> +	/*
> +	 * We still need *_set_rps to process the new max_delay and
> +	 * update the interrupt limits and PMINTRMSK even though
> +	 * frequency request may be unchanged.
> +	 */
> +	intel_rps_set(rps, val);
> +
> +unlock:
> +	mutex_unlock(&rps->lock);
> +
> +	return ret;
> +}
> +
> +u32 intel_rps_get_min_frequency(struct intel_rps *rps)
> +{
> +	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
> +
> +	if (rps_uses_slpc(rps))
> +		return slpc->min_freq_softlimit;
> +	else
> +		return intel_gpu_freq(rps, rps->min_freq_softlimit);
> +}
> +
> +int intel_rps_set_min_frequency(struct intel_rps *rps, u32 val)
> +{
> +	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
> +	int ret;
> +
> +	if (rps_uses_slpc(rps))
> +		return intel_guc_slpc_set_min_freq(slpc, val);
> +
> +	mutex_lock(&rps->lock);
> +
> +	val = intel_freq_opcode(rps, val);
> +	if (val < rps->min_freq ||
> +	    val > rps->max_freq ||
> +	    val > rps->max_freq_softlimit) {
> +		ret = -EINVAL;
> +		goto unlock;
> +	}
> +
> +	rps->min_freq_softlimit = val;
> +
> +	val = clamp_t(int, rps->cur_freq,
> +		      rps->min_freq_softlimit,
> +		      rps->max_freq_softlimit);
> +
> +	/*
> +	 * We still need *_set_rps to process the new min_delay and
> +	 * update the interrupt limits and PMINTRMSK even though
> +	 * frequency request may be unchanged.
> +	 */
> +	intel_rps_set(rps, val);
> +
> +unlock:
> +	mutex_unlock(&rps->lock);
> +
> +	return ret;
> +}
> +
>  /* External interface for intel_ips.ko */
>  
>  static struct drm_i915_private __rcu *ips_mchdev;
> diff --git a/drivers/gpu/drm/i915/gt/intel_rps.h b/drivers/gpu/drm/i915/gt/intel_rps.h
> index 1d2cfc98b510..9a09ff5ebf64 100644
> --- a/drivers/gpu/drm/i915/gt/intel_rps.h
> +++ b/drivers/gpu/drm/i915/gt/intel_rps.h
> @@ -31,6 +31,11 @@ int intel_gpu_freq(struct intel_rps *rps, int val);
>  int intel_freq_opcode(struct intel_rps *rps, int val);
>  u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat1);
>  u32 intel_rps_read_actual_frequency(struct intel_rps *rps);
> +u32 intel_rps_get_requested_frequency(struct intel_rps *rps);
> +u32 intel_rps_get_min_frequency(struct intel_rps *rps);
> +int intel_rps_set_min_frequency(struct intel_rps *rps, u32 val);
> +u32 intel_rps_get_max_frequency(struct intel_rps *rps);
> +int intel_rps_set_max_frequency(struct intel_rps *rps, u32 val);
>  
>  void gen5_rps_irq_handler(struct intel_rps *rps);
>  void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir);
> diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c
> index 34d37d46a126..a896bec18255 100644
> --- a/drivers/gpu/drm/i915/i915_pmu.c
> +++ b/drivers/gpu/drm/i915/i915_pmu.c
> @@ -407,7 +407,7 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns)
>  
>  	if (pmu->enable & config_mask(I915_PMU_REQUESTED_FREQUENCY)) {
>  		add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_REQ],
> -				intel_gpu_freq(rps, rps->cur_freq),
> +				intel_rps_get_requested_frequency(rps),
>  				period_ns / 1000);
>  	}
>  
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 7d9e90aa3ec0..8ab3c2f8f8e4 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -9195,6 +9195,8 @@ enum {
>  #define   GEN9_FREQUENCY(x)			((x) << 23)
>  #define   GEN6_OFFSET(x)			((x) << 19)
>  #define   GEN6_AGGRESSIVE_TURBO			(0 << 15)
> +#define   GEN9_SW_REQ_UNSLICE_RATIO_SHIFT 	23
> +
>  #define GEN6_RC_VIDEO_FREQ			_MMIO(0xA00C)
>  #define GEN6_RC_CONTROL				_MMIO(0xA090)
>  #define   GEN6_RC_CTL_RC6pp_ENABLE		(1 << 16)
> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
> index 873bf996ceb5..f2eee8491b19 100644
> --- a/drivers/gpu/drm/i915/i915_sysfs.c
> +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> @@ -272,7 +272,7 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
>  	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
>  	struct intel_rps *rps = &i915->gt.rps;
>  
> -	return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->cur_freq));
> +	return sysfs_emit(buf, "%d\n", intel_rps_get_requested_frequency(rps));
>  }
>  
>  static ssize_t gt_boost_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
> @@ -326,9 +326,10 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev,
>  static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
>  {
>  	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> -	struct intel_rps *rps = &dev_priv->gt.rps;
> +	struct intel_gt *gt = &dev_priv->gt;
> +	struct intel_rps *rps = &gt->rps;
>  
> -	return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->max_freq_softlimit));
> +	return sysfs_emit(buf, "%d\n", intel_rps_get_max_frequency(rps));
>  }
>  
>  static ssize_t gt_max_freq_mhz_store(struct device *kdev,
> @@ -336,7 +337,8 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
>  				     const char *buf, size_t count)
>  {
>  	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> -	struct intel_rps *rps = &dev_priv->gt.rps;
> +	struct intel_gt *gt = &dev_priv->gt;
> +	struct intel_rps *rps = &gt->rps;
>  	ssize_t ret;
>  	u32 val;
>  
> @@ -344,35 +346,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
>  	if (ret)
>  		return ret;
>  
> -	mutex_lock(&rps->lock);
> -
> -	val = intel_freq_opcode(rps, val);
> -	if (val < rps->min_freq ||
> -	    val > rps->max_freq ||
> -	    val < rps->min_freq_softlimit) {
> -		ret = -EINVAL;
> -		goto unlock;
> -	}
> -
> -	if (val > rps->rp0_freq)
> -		DRM_DEBUG("User requested overclocking to %d\n",
> -			  intel_gpu_freq(rps, val));
> -
> -	rps->max_freq_softlimit = val;
> -
> -	val = clamp_t(int, rps->cur_freq,
> -		      rps->min_freq_softlimit,
> -		      rps->max_freq_softlimit);
> -
> -	/*
> -	 * We still need *_set_rps to process the new max_delay and
> -	 * update the interrupt limits and PMINTRMSK even though
> -	 * frequency request may be unchanged.
> -	 */
> -	intel_rps_set(rps, val);
> -
> -unlock:
> -	mutex_unlock(&rps->lock);
> +	ret = intel_rps_set_max_frequency(rps, val);
>  
>  	return ret ?: count;
>  }
> @@ -380,9 +354,10 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
>  static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
>  {
>  	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> -	struct intel_rps *rps = &dev_priv->gt.rps;
> +	struct intel_gt *gt = &dev_priv->gt;
> +	struct intel_rps *rps = &gt->rps;
>  
> -	return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->min_freq_softlimit));
> +	return sysfs_emit(buf, "%d\n", intel_rps_get_min_frequency(rps));
>  }
>  
>  static ssize_t gt_min_freq_mhz_store(struct device *kdev,
> @@ -398,31 +373,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
>  	if (ret)
>  		return ret;
>  
> -	mutex_lock(&rps->lock);
> -
> -	val = intel_freq_opcode(rps, val);
> -	if (val < rps->min_freq ||
> -	    val > rps->max_freq ||
> -	    val > rps->max_freq_softlimit) {
> -		ret = -EINVAL;
> -		goto unlock;
> -	}
> -
> -	rps->min_freq_softlimit = val;
> -
> -	val = clamp_t(int, rps->cur_freq,
> -		      rps->min_freq_softlimit,
> -		      rps->max_freq_softlimit);
> -
> -	/*
> -	 * We still need *_set_rps to process the new min_delay and
> -	 * update the interrupt limits and PMINTRMSK even though
> -	 * frequency request may be unchanged.
> -	 */
> -	intel_rps_set(rps, val);
> -
> -unlock:
> -	mutex_unlock(&rps->lock);
> +	ret = intel_rps_set_min_frequency(rps, val);
>  
>  	return ret ?: count;
>  }
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 15/16] drm/i915/guc/slpc: slpc selftest
  2021-07-10  1:20 ` [PATCH 15/16] drm/i915/guc/slpc: slpc selftest Vinay Belgaumkar
@ 2021-07-10 18:29   ` Michal Wajdeczko
  2021-07-21  1:06     ` Belgaumkar, Vinay
  0 siblings, 1 reply; 49+ messages in thread
From: Michal Wajdeczko @ 2021-07-10 18:29 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel



On 10.07.2021 03:20, Vinay Belgaumkar wrote:
> Tests that exercise the slpc get/set frequency interfaces.
> 
> Clamp_max will set max frequency to multiple levels and check
> that slpc requests frequency lower than or equal to it.
> 
> Clamp_min will set min frequency to different levels and check
> if slpc requests are higher or equal to those levels.

2x s/slpc/SLPC

> 
> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
> ---
>  drivers/gpu/drm/i915/gt/intel_rps.c           |   1 +
>  drivers/gpu/drm/i915/gt/selftest_slpc.c       | 333 ++++++++++++++++++
>  drivers/gpu/drm/i915/gt/selftest_slpc.h       |  12 +
>  .../drm/i915/selftests/i915_live_selftests.h  |   1 +
>  4 files changed, 347 insertions(+)
>  create mode 100644 drivers/gpu/drm/i915/gt/selftest_slpc.c
>  create mode 100644 drivers/gpu/drm/i915/gt/selftest_slpc.h
> 
> diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c
> index 88ffc5d90730..16ac2e840881 100644
> --- a/drivers/gpu/drm/i915/gt/intel_rps.c
> +++ b/drivers/gpu/drm/i915/gt/intel_rps.c
> @@ -2288,4 +2288,5 @@ EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
>  
>  #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
>  #include "selftest_rps.c"
> +#include "selftest_slpc.c"
>  #endif
> diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c b/drivers/gpu/drm/i915/gt/selftest_slpc.c
> new file mode 100644
> index 000000000000..f440c1cb2afa
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c
> @@ -0,0 +1,333 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2020 Intel Corporation

2021

> + */
> +#include "selftest_slpc.h"
> +#include "selftest_rps.h"
> +
> +#include <linux/pm_qos.h>
> +#include <linux/sort.h>

system headers should go first

> +
> +#include "intel_engine_heartbeat.h"
> +#include "intel_engine_pm.h"
> +#include "intel_gpu_commands.h"
> +#include "intel_gt_clock_utils.h"
> +#include "intel_gt_pm.h"
> +#include "intel_rc6.h"
> +#include "selftest_engine_heartbeat.h"
> +#include "intel_rps.h"
> +#include "selftests/igt_flush_test.h"
> +#include "selftests/igt_spinner.h"

wrong order ?

> +
> +#define NUM_STEPS 5
> +#define H2G_DELAY 50000
> +#define delay_for_h2g() usleep_range(H2G_DELAY, H2G_DELAY + 10000)
> +
> +static int set_min_freq(struct intel_guc_slpc *slpc, int freq)
> +{
> +	int ret;

add empty line

> +	ret = intel_guc_slpc_set_min_freq(slpc, freq);
> +	if (ret) {
> +		pr_err("Could not set min frequency to [%d]\n", freq);
> +		return ret;
> +	} else {
> +		/* Delay to ensure h2g completes */
> +		delay_for_h2g();
> +	}
> +
> +	return ret;
> +}
> +
> +static int set_max_freq(struct intel_guc_slpc *slpc, int freq)
> +{
> +	int ret;

add empty line

> +	ret = intel_guc_slpc_set_max_freq(slpc, freq);
> +	if (ret) {
> +		pr_err("Could not set maximum frequency [%d]\n",
> +			freq);
> +		return ret;
> +	} else {
> +		/* Delay to ensure h2g completes */
> +		delay_for_h2g();
> +	}
> +
> +	return ret;
> +}
> +
> +int live_slpc_clamp_min(void *arg)
> +{
> +	struct drm_i915_private *i915 = arg;
> +	struct intel_gt *gt = &i915->gt;
> +	struct intel_guc_slpc *slpc;
> +	struct intel_rps *rps;
> +	struct intel_engine_cs *engine;
> +	enum intel_engine_id id;
> +	struct igt_spinner spin;
> +	int err = 0;

usually "err" is last decl

> +	u32 slpc_min_freq, slpc_max_freq;
> +
> +

too many empty lines

> +	slpc = &gt->uc.guc.slpc;
> +	rps = &gt->rps;

could be initialized in decl above

> +
> +	if (!intel_uc_uses_guc_slpc(&gt->uc))
> +		return 0;
> +
> +	if (igt_spinner_init(&spin, gt))
> +		return -ENOMEM;
> +
> +	if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) {
> +		pr_err("Could not get SLPC max freq");
> +		return -EIO;
> +	}
> +
> +	if (intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq)) {
> +		pr_err("Could not get SLPC min freq");
> +		return -EIO;
> +	}
> +
> +	if (slpc_min_freq == slpc_max_freq) {
> +		pr_err("Min/Max are fused to the same value");
> +		return -EINVAL;
> +	}

3x missing \n

> +
> +	intel_gt_pm_wait_for_idle(gt);
> +	intel_gt_pm_get(gt);
> +	for_each_engine(engine, gt, id) {
> +		struct i915_request *rq;
> +		u32 step, min_freq, req_freq;
> +		u32 act_freq, max_act_freq;
> +
> +		if (!intel_engine_can_store_dword(engine))
> +			continue;
> +
> +		/* Go from min to max in 5 steps */
> +		step = (slpc_max_freq - slpc_min_freq)/NUM_STEPS;

add spaces ") / NUM"

> +		max_act_freq = slpc_min_freq;
> +		for (min_freq = slpc_min_freq; min_freq < slpc_max_freq; min_freq+=step)

add spaces " += "

> +		{
> +			err = set_min_freq(slpc, min_freq);
> +			if (err)
> +				break;
> +
> +			st_engine_heartbeat_disable(engine);
> +
> +

keep only one empty line

> +			rq = igt_spinner_create_request(&spin,
> +					engine->kernel_context,
> +					MI_NOOP);
> +			if (IS_ERR(rq)) {
> +				err = PTR_ERR(rq);
> +				st_engine_heartbeat_enable(engine);
> +				break;
> +			}
> +
> +			i915_request_add(rq);
> +
> +			if (!igt_wait_for_spinner(&spin, rq)) {
> +				pr_err("%s: Spinner did not start\n",
> +					engine->name);
> +				igt_spinner_end(&spin);
> +				st_engine_heartbeat_enable(engine);
> +				intel_gt_set_wedged(engine->gt);
> +				err = -EIO;
> +				break;
> +			}
> +
> +			/* Wait for GuC to detect business and raise
> +			 * requested frequency if necessary */
> +			delay_for_h2g();
> +
> +			req_freq = intel_rps_read_punit_req_frequency(rps);
> +
> +			/* GuC requests freq in multiples of 50/3 MHz */
> +			if (req_freq < (min_freq - 50/3)) {
> +				pr_err("SWReq is %d, should be at least %d", req_freq,
> +					min_freq - 50/3);
> +				igt_spinner_end(&spin);
> +				st_engine_heartbeat_enable(engine);
> +				err = -EINVAL;
> +				break;
> +			}
> +
> +			act_freq =  intel_rps_read_actual_frequency(rps);
> +			if (act_freq > max_act_freq)
> +				max_act_freq = act_freq;
> +
> +			igt_spinner_end(&spin);
> +			st_engine_heartbeat_enable(engine);
> +		}
> +
> +		pr_info("Max actual frequency for %s was %d",
> +				engine->name, max_act_freq);
> +
> +		/* Actual frequency should rise above min */
> +		if (max_act_freq == slpc_min_freq) {
> +			pr_err("Actual freq did not rise above min");
> +			err = -EINVAL;
> +		}

2x missing \n

and few more below

> +
> +		if (err)
> +			break;
> +	}
> +
> +	/* Restore min/max frequencies */
> +	set_max_freq(slpc, slpc_max_freq);
> +	set_min_freq(slpc, slpc_min_freq);
> +
> +	if (igt_flush_test(gt->i915))
> +		err = -EIO;
> +
> +	intel_gt_pm_put(gt);
> +	igt_spinner_fini(&spin);
> +	intel_gt_pm_wait_for_idle(gt);
> +
> +	return err;
> +}
> +
> +int live_slpc_clamp_max(void *arg)
> +{
> +	struct drm_i915_private *i915 = arg;
> +	struct intel_gt *gt = &i915->gt;
> +	struct intel_guc_slpc *slpc;
> +	struct intel_rps *rps;
> +	struct intel_engine_cs *engine;
> +	enum intel_engine_id id;
> +	struct igt_spinner spin;
> +	int err = 0;
> +	u32 slpc_min_freq, slpc_max_freq;
> +
> +	slpc = &gt->uc.guc.slpc;
> +	rps = &gt->rps;
> +
> +	if (!intel_uc_uses_guc_slpc(&gt->uc))
> +		return 0;
> +
> +	if (igt_spinner_init(&spin, gt))
> +		return -ENOMEM;
> +
> +	if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) {
> +		pr_err("Could not get SLPC max freq");
> +		return -EIO;
> +	}
> +
> +	if (intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq)) {
> +		pr_err("Could not get SLPC min freq");
> +		return -EIO;
> +	}
> +
> +	if (slpc_min_freq == slpc_max_freq) {
> +		pr_err("Min/Max are fused to the same value");
> +		return -EINVAL;
> +	}
> +
> +	intel_gt_pm_wait_for_idle(gt);
> +	intel_gt_pm_get(gt);
> +	for_each_engine(engine, gt, id) {
> +		struct i915_request *rq;
> +		u32 max_freq, req_freq;
> +		u32 act_freq, max_act_freq;
> +		u32 step;
> +
> +		if (!intel_engine_can_store_dword(engine))
> +			continue;
> +
> +		/* Go from max to min in 5 steps */
> +		step = (slpc_max_freq - slpc_min_freq)/NUM_STEPS;
> +		max_act_freq = slpc_min_freq;
> +		for (max_freq = slpc_max_freq; max_freq > slpc_min_freq; max_freq-=step)
> +		{
> +			err = set_max_freq(slpc, max_freq);
> +			if (err)
> +				break;
> +
> +			st_engine_heartbeat_disable(engine);
> +
> +			rq = igt_spinner_create_request(&spin,
> +						engine->kernel_context,
> +						MI_NOOP);
> +			if (IS_ERR(rq)) {
> +				st_engine_heartbeat_enable(engine);
> +				err = PTR_ERR(rq);
> +				break;
> +			}
> +
> +			i915_request_add(rq);
> +
> +			if (!igt_wait_for_spinner(&spin, rq)) {
> +				pr_err("%s: SLPC spinner did not start\n",
> +				       engine->name);
> +				igt_spinner_end(&spin);
> +				st_engine_heartbeat_enable(engine);
> +				intel_gt_set_wedged(engine->gt);
> +				err = -EIO;
> +				break;
> +			}
> +
> +			delay_for_h2g();
> +
> +			/* Verify that SWREQ indeed was set to specific value */
> +			req_freq = intel_rps_read_punit_req_frequency(rps);
> +
> +			/* GuC requests freq in multiples of 50/3 MHz */
> +			if (req_freq > (max_freq + 50/3)) {
> +				pr_err("SWReq is %d, should be at most %d", req_freq,
> +					max_freq + 50/3);
> +				igt_spinner_end(&spin);
> +				st_engine_heartbeat_enable(engine);
> +				err = -EINVAL;
> +				break;
> +			}
> +
> +			act_freq =  intel_rps_read_actual_frequency(rps);
> +			if (act_freq > max_act_freq)
> +				max_act_freq = act_freq;
> +
> +			st_engine_heartbeat_enable(engine);
> +			igt_spinner_end(&spin);
> +
> +			if (err)
> +				break;
> +		}
> +
> +		pr_info("Max actual frequency for %s was %d",
> +				engine->name, max_act_freq);
> +
> +		/* Actual frequency should rise above min */
> +		if (max_act_freq == slpc_min_freq) {
> +			pr_err("Actual freq did not rise above min");
> +			err = -EINVAL;
> +		}
> +
> +		if (igt_flush_test(gt->i915)) {
> +			err = -EIO;
> +			break;
> +		}
> +
> +		if (err)
> +			break;
> +	}
> +
> +	/* Restore min/max freq */
> +	set_max_freq(slpc, slpc_max_freq);
> +	set_min_freq(slpc, slpc_min_freq);
> +
> +	intel_gt_pm_put(gt);
> +	igt_spinner_fini(&spin);
> +	intel_gt_pm_wait_for_idle(gt);
> +
> +	return err;
> +}
> +
> +int intel_slpc_live_selftests(struct drm_i915_private *i915)
> +{
> +	static const struct i915_subtest tests[] = {
> +		SUBTEST(live_slpc_clamp_max),
> +		SUBTEST(live_slpc_clamp_min),
> +	};
> +
> +	if (intel_gt_is_wedged(&i915->gt))
> +		return 0;
> +
> +	return i915_live_subtests(tests, i915);
> +}
> diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.h b/drivers/gpu/drm/i915/gt/selftest_slpc.h
> new file mode 100644
> index 000000000000..8dfb40916a8c
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gt/selftest_slpc.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2020 Intel Corporation

2021

Michal

> + */
> +
> +#ifndef SELFTEST_SLPC_H
> +#define SELFTEST_SLPC_H
> +
> +int live_slpc_clamp_max(void *arg);
> +int live_slpc_clamp_min(void *arg);
> +
> +#endif /* SELFTEST_SLPC_H */
> diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> index e2fd1b61af71..1746a56dda06 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> @@ -47,5 +47,6 @@ selftest(hangcheck, intel_hangcheck_live_selftests)
>  selftest(execlists, intel_execlists_live_selftests)
>  selftest(ring_submission, intel_ring_submission_live_selftests)
>  selftest(perf, i915_perf_live_selftests)
> +selftest(slpc, intel_slpc_live_selftests)
>  /* Here be dragons: keep last to run last! */
>  selftest(late_gt_pm, intel_gt_pm_late_selftests)
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Intel-gfx] [PATCH 16/16] drm/i915/guc/rc: Setup and enable GUCRC feature
  2021-07-10  1:20 ` [PATCH 16/16] drm/i915/guc/rc: Setup and enable GUCRC feature Vinay Belgaumkar
@ 2021-07-10 18:41   ` Michal Wajdeczko
  2021-07-21  1:11     ` Belgaumkar, Vinay
  0 siblings, 1 reply; 49+ messages in thread
From: Michal Wajdeczko @ 2021-07-10 18:41 UTC (permalink / raw)
  To: Vinay Belgaumkar, intel-gfx, dri-devel



On 10.07.2021 03:20, Vinay Belgaumkar wrote:
> This feature hands over the control of HW RC6 to the GUC.
> GUC decides when to put HW into RC6 based on it's internal
> busyness algorithms.
> 
> GUCRC needs GUC submission to be enabled, and only
> supported on Gen12+ for now.
> 
> When GUCRC is enabled, do not set HW RC6. Use a H2G message
> to tell guc to enable GUCRC. When disabling RC6, tell guc to

s/GUC/GuC
s/guc/GuC

> revert RC6 control back to KMD.
> 
> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile                 |  1 +
>  drivers/gpu/drm/i915/gt/intel_rc6.c           | 22 ++++--
>  .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h  |  6 ++
>  drivers/gpu/drm/i915/gt/uc/intel_guc.c        |  1 +
>  drivers/gpu/drm/i915/gt/uc/intel_guc.h        |  2 +
>  drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c     | 79 +++++++++++++++++++
>  drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h     | 32 ++++++++
>  drivers/gpu/drm/i915/gt/uc/intel_uc.h         |  2 +
>  8 files changed, 140 insertions(+), 5 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
>  create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index d8eac4468df9..3fc17f20d88e 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -186,6 +186,7 @@ i915-y += gt/uc/intel_uc.o \
>  	  gt/uc/intel_guc_fw.o \
>  	  gt/uc/intel_guc_log.o \
>  	  gt/uc/intel_guc_log_debugfs.o \
> +	  gt/uc/intel_guc_rc.o \
>  	  gt/uc/intel_guc_slpc.o \
>  	  gt/uc/intel_guc_submission.o \
>  	  gt/uc/intel_huc.o \
> diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c
> index 259d7eb4e165..299fcf10b04b 100644
> --- a/drivers/gpu/drm/i915/gt/intel_rc6.c
> +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c
> @@ -98,11 +98,19 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6)
>  	set(uncore, GEN9_MEDIA_PG_IDLE_HYSTERESIS, 60);
>  	set(uncore, GEN9_RENDER_PG_IDLE_HYSTERESIS, 60);
>  
> -	/* 3a: Enable RC6 */
> -	rc6->ctl_enable =
> -		GEN6_RC_CTL_HW_ENABLE |
> -		GEN6_RC_CTL_RC6_ENABLE |
> -		GEN6_RC_CTL_EI_MODE(1);
> +	/* 3a: Enable RC6
> +	 *
> +	 * With GUCRC, we do not enable bit 31 of RC_CTL,
> +	 * thus allowing GuC to control RC6 entry/exit fully instead.
> +	 * We will not set the HW ENABLE and EI bits
> +	 */
> +	if (!intel_guc_rc_enable(&gt->uc.guc))
> +		rc6->ctl_enable = GEN6_RC_CTL_RC6_ENABLE;
> +	else
> +		rc6->ctl_enable =
> +			GEN6_RC_CTL_HW_ENABLE |
> +			GEN6_RC_CTL_RC6_ENABLE |
> +			GEN6_RC_CTL_EI_MODE(1);
>  
>  	pg_enable =
>  		GEN9_RENDER_PG_ENABLE |
> @@ -513,6 +521,10 @@ static void __intel_rc6_disable(struct intel_rc6 *rc6)
>  {
>  	struct drm_i915_private *i915 = rc6_to_i915(rc6);
>  	struct intel_uncore *uncore = rc6_to_uncore(rc6);
> +	struct intel_gt *gt = rc6_to_gt(rc6);
> +
> +	/* Take control of RC6 back from GuC */
> +	intel_guc_rc_disable(&gt->uc.guc);
>  
>  	intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
>  	if (GRAPHICS_VER(i915) >= 9)
> diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
> index 596cf4b818e5..2ddb9cdc0a59 100644
> --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
> +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
> @@ -136,6 +136,7 @@ enum intel_guc_action {
>  	INTEL_GUC_ACTION_CONTEXT_RESET_NOTIFICATION = 0x1008,
>  	INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION = 0x1009,
>  	INTEL_GUC_ACTION_SLPC_REQUEST = 0x3003,
> +	INTEL_GUC_ACTION_SETUP_PC_GUCRC = 0x3004,
>  	INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000,
>  	INTEL_GUC_ACTION_REGISTER_CONTEXT = 0x4502,
>  	INTEL_GUC_ACTION_DEREGISTER_CONTEXT = 0x4503,
> @@ -146,6 +147,11 @@ enum intel_guc_action {
>  	INTEL_GUC_ACTION_LIMIT
>  };
>  
> +enum intel_guc_rc_options {
> +	INTEL_GUCRC_HOST_CONTROL,
> +	INTEL_GUCRC_FIRMWARE_CONTROL,
> +};
> +
>  enum intel_guc_preempt_options {
>  	INTEL_GUC_PREEMPT_OPTION_DROP_WORK_Q = 0x4,
>  	INTEL_GUC_PREEMPT_OPTION_DROP_SUBMIT_Q = 0x8,
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> index 82863a9bc8e8..0d55b24f7c67 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> @@ -158,6 +158,7 @@ void intel_guc_init_early(struct intel_guc *guc)
>  	intel_guc_log_init_early(&guc->log);
>  	intel_guc_submission_init_early(guc);
>  	intel_guc_slpc_init_early(guc);
> +	intel_guc_rc_init_early(guc);
>  
>  	mutex_init(&guc->send_mutex);
>  	spin_lock_init(&guc->irq_lock);
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> index 0dbbd9cf553f..592d52e5e93c 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> @@ -59,6 +59,8 @@ struct intel_guc {
>  
>  	bool submission_supported;
>  	bool submission_selected;
> +	bool rc_supported;
> +	bool rc_selected;
>  	bool slpc_supported;
>  	bool slpc_selected;
>  
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
> new file mode 100644
> index 000000000000..45b61432c56d
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
> @@ -0,0 +1,79 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2020 Intel Corporation

2021

> +*/

unaligned *

> +
> +#include "intel_guc_rc.h"
> +#include "gt/intel_gt.h"
> +#include "i915_drv.h"
> +
> +static bool __guc_rc_supported(struct intel_guc *guc)
> +{
> +	/* GuC RC is unavailable for pre-Gen12 */
> +	return guc->submission_supported &&
> +		GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12;
> +}
> +
> +static bool __guc_rc_selected(struct intel_guc *guc)
> +{
> +	if (!intel_guc_rc_is_supported(guc))
> +		return false;
> +
> +	return guc->submission_selected;
> +}
> +
> +void intel_guc_rc_init_early(struct intel_guc *guc)
> +{
> +	guc->rc_supported = __guc_rc_supported(guc);
> +	guc->rc_selected = __guc_rc_selected(guc);
> +}
> +
> +static int guc_action_control_gucrc(struct intel_guc *guc, bool enable)
> +{
> +	struct drm_device *drm = &guc_to_gt(guc)->i915->drm;
> +	u32 rc_mode = enable ? INTEL_GUCRC_FIRMWARE_CONTROL :
> +				INTEL_GUCRC_HOST_CONTROL;
> +	u32 action[] = {
> +		INTEL_GUC_ACTION_SETUP_PC_GUCRC,
> +		rc_mode
> +	};
> +	int ret;
> +
> +	ret = intel_guc_send(guc, action, ARRAY_SIZE(action));
> +	if (ret)

since intel_guc_send() may return non-zero value from data0 RESPONSE
field, assuming that this action expects there MBZ this should be:

	ret = ret > 0 ? -EPROTO : ret;

otherwise some static code analyzers might complain

> +		drm_err(drm, "Failed to set GUCRC mode(%d), err=%d\n",

you may want to print error with %pe
and move this message to __guc_rc_control because of the above

> +			rc_mode, ret);
> +
> +	return ret;
> +}
> +
> +static int __guc_rc_control(struct intel_guc *guc, bool enable)
> +{
> +	struct intel_gt *gt = guc_to_gt(guc);
> +	int ret;
> +
> +	if (!intel_uc_uses_guc_rc(&gt->uc))
> +		return -ENOTSUPP;
> +
> +	if (!intel_guc_is_ready(guc))
> +		return -EINVAL;
> +
> +	ret = guc_action_control_gucrc(guc, enable);
> +	if (unlikely(ret))

	drm_err(drm, "Failed to %s GuC RC mode (%pe)\n",
		enabledisable(enable), ERR_PTR(ret));

> +		return ret;
> +
> +	drm_info(&gt->i915->drm, "GuC RC %s\n",
> +	         enableddisabled(enable));
> +
> +	return 0;
> +}
> +
> +int intel_guc_rc_enable(struct intel_guc *guc)
> +{
> +	return __guc_rc_control(guc, true);
> +}
> +
> +int intel_guc_rc_disable(struct intel_guc *guc)
> +{
> +	return __guc_rc_control(guc, false);
> +}
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h
> new file mode 100644
> index 000000000000..169e60726e5b
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h
> @@ -0,0 +1,32 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2020 Intel Corporation

2021

> + */
> +
> +#ifndef _INTEL_GUC_RC_H_
> +#define _INTEL_GUC_RC_H_
> +
> +#include <linux/types.h>

do you need this include here ?

Michal

> +#include "intel_guc_submission.h"
> +
> +void intel_guc_rc_init_early(struct intel_guc *guc);
> +
> +static inline bool intel_guc_rc_is_supported(struct intel_guc *guc)
> +{
> +	return guc->rc_supported;
> +}
> +
> +static inline bool intel_guc_rc_is_wanted(struct intel_guc *guc)
> +{
> +	return guc->submission_selected && intel_guc_rc_is_supported(guc);
> +}
> +
> +static inline bool intel_guc_rc_is_used(struct intel_guc *guc)
> +{
> +	return intel_guc_submission_is_used(guc) && intel_guc_rc_is_wanted(guc);
> +}
> +
> +int intel_guc_rc_enable(struct intel_guc *guc);
> +int intel_guc_rc_disable(struct intel_guc *guc);
> +
> +#endif
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.h b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
> index 38e465fd8a0c..29d8ad6d9087 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
> @@ -7,6 +7,7 @@
>  #define _INTEL_UC_H_
>  
>  #include "intel_guc.h"
> +#include "intel_guc_rc.h"
>  #include "intel_guc_submission.h"
>  #include "intel_huc.h"
>  #include "i915_params.h"
> @@ -84,6 +85,7 @@ uc_state_checkers(guc, guc);
>  uc_state_checkers(huc, huc);
>  uc_state_checkers(guc, guc_submission);
>  uc_state_checkers(guc, guc_slpc);
> +uc_state_checkers(guc, guc_rc);
>  
>  #undef uc_state_checkers
>  #undef __uc_state_checker
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 02/16] drm/i915/guc/slpc: Initial definitions for slpc
  2021-07-10 14:27   ` Michal Wajdeczko
@ 2021-07-12 18:40     ` Belgaumkar, Vinay
  2021-07-12 23:43     ` Belgaumkar, Vinay
  1 sibling, 0 replies; 49+ messages in thread
From: Belgaumkar, Vinay @ 2021-07-12 18:40 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx, dri-devel
  Cc: Daniele Ceraolo Spurio, Sundaresan Sujaritha



On 7/10/2021 7:27 AM, Michal Wajdeczko wrote:
> Hi Vinay,
> 
> On 10.07.2021 03:20, Vinay Belgaumkar wrote:
>> Add macros to check for slpc support. This feature is currently supported
>> for gen12+ and enabled whenever guc submission is enabled/selected.
> 
> please try to use consistent names across all patches:
> 
> s/slpc/SLPC
> s/gen12/Gen12
> s/guc/GuC
> 
>>
>> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
>> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>> ---
>>   drivers/gpu/drm/i915/gt/uc/intel_guc.c        |  1 +
>>   drivers/gpu/drm/i915/gt/uc/intel_guc.h        |  2 ++
>>   .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 21 +++++++++++++++++++
>>   .../gpu/drm/i915/gt/uc/intel_guc_submission.h | 16 ++++++++++++++
>>   drivers/gpu/drm/i915/gt/uc/intel_uc.c         |  6 ++++--
>>   drivers/gpu/drm/i915/gt/uc/intel_uc.h         |  1 +
>>   6 files changed, 45 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> index 979128e28372..b9a809f2d221 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> @@ -157,6 +157,7 @@ void intel_guc_init_early(struct intel_guc *guc)
>>   	intel_guc_ct_init_early(&guc->ct);
>>   	intel_guc_log_init_early(&guc->log);
>>   	intel_guc_submission_init_early(guc);
>> +	intel_guc_slpc_init_early(guc);
>>   
>>   	mutex_init(&guc->send_mutex);
>>   	spin_lock_init(&guc->irq_lock);
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
>> index 5d94cf482516..e5a456918b88 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
>> @@ -57,6 +57,8 @@ struct intel_guc {
>>   
>>   	bool submission_supported;
>>   	bool submission_selected;
>> +	bool slpc_supported;
>> +	bool slpc_selected;
>>   
>>   	struct i915_vma *ads_vma;
>>   	struct __guc_ads_blob *ads_blob;
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
>> index 9c102bf0c8e3..e2644a05f298 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
>> @@ -2351,6 +2351,27 @@ void intel_guc_submission_init_early(struct intel_guc *guc)
>>   	guc->submission_selected = __guc_submission_selected(guc);
>>   }
>>   
>> +static bool __guc_slpc_supported(struct intel_guc *guc)
> 
> hmm, easy to confuse with intel_guc_slpc_is_supported, so maybe:
> 
> __detect_slpc_supported()

ok.
> 
> (yes, I know you were following code above)
> 
>> +{
>> +	/* GuC slpc is unavailable for pre-Gen12 */
> 
> s/slpc/SLPC
> 
>> +	return guc->submission_supported &&
>> +		GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12;
>> +}
>> +
>> +static bool __guc_slpc_selected(struct intel_guc *guc)
>> +{
>> +	if (!intel_guc_slpc_is_supported(guc))
>> +		return false;
>> +
>> +	return guc->submission_selected;
>> +}
>> +
>> +void intel_guc_slpc_init_early(struct intel_guc *guc)
>> +{
>> +	guc->slpc_supported = __guc_slpc_supported(guc);
>> +	guc->slpc_selected = __guc_slpc_selected(guc);
>> +}
> 
> in patch 4/16 you are introducing intel_guc_slpc.c|h so to have proper
> encapsulation better to define this function as
> 
> void intel_guc_slpc_init_early(struct intel_guc_slpc *slpc) { }

the uc_state_checkers force the use of struct intel_guc *guc as the 
param. don't think I can change that to refer to slpc instead.

static inline bool intel_guc_slpc_is_supported(struct intel_guc *guc)
{
         return guc->slpc_supported;
}

slpc_supported needs to be inside the guc struct.

> 
> and move it to intel_guc_slpc.c
> 
>> +
>>   static inline struct intel_context *
>>   g2h_context_lookup(struct intel_guc *guc, u32 desc_idx)
>>   {
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
>> index be767eb6ff71..7ae5fd052faf 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
>> @@ -13,6 +13,7 @@
>>   struct drm_printer;
>>   struct intel_engine_cs;
>>   
>> +void intel_guc_slpc_init_early(struct intel_guc *guc);
> 
> it really does not belong to this .h
> 
>>   void intel_guc_submission_init_early(struct intel_guc *guc);
>>   int intel_guc_submission_init(struct intel_guc *guc);
>>   void intel_guc_submission_enable(struct intel_guc *guc);
>> @@ -50,4 +51,19 @@ static inline bool intel_guc_submission_is_used(struct intel_guc *guc)
>>   	return intel_guc_is_used(guc) && intel_guc_submission_is_wanted(guc);
>>   }
>>   
>> +static inline bool intel_guc_slpc_is_supported(struct intel_guc *guc)
>> +{
>> +	return guc->slpc_supported;
>> +}
>> +
>> +static inline bool intel_guc_slpc_is_wanted(struct intel_guc *guc)
>> +{
>> +	return guc->slpc_selected;
>> +}
>> +
>> +static inline bool intel_guc_slpc_is_used(struct intel_guc *guc)
>> +{
>> +	return intel_guc_submission_is_used(guc) && intel_guc_slpc_is_wanted(guc);
>> +}
> 
> did you try to define them in intel_guc_slpc.h ?
> 
> note that to avoid circular dependencies you can define slpc struct in
> intel_guc_slpc_types.h and then
> 
> in intel_guc.h:
> 	#include "intel_guc_slpc_types.h" instead of intel_guc_slpc.h
> 
> in intel_guc_slpc.h:
> 	#include "intel_guc.h"
> 	#include "intel_guc_slpc_types.h"
> 	#include "intel_guc_submission.h"

Sure, will give that a try.

> 
>> +
>>   #endif
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
>> index 61be0aa81492..dca5f6d0641b 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
>> @@ -76,16 +76,18 @@ static void __confirm_options(struct intel_uc *uc)
>>   	struct drm_i915_private *i915 = uc_to_gt(uc)->i915;
>>   
>>   	drm_dbg(&i915->drm,
>> -		"enable_guc=%d (guc:%s submission:%s huc:%s)\n",
>> +		"enable_guc=%d (guc:%s submission:%s huc:%s slpc:%s)\n",
>>   		i915->params.enable_guc,
>>   		yesno(intel_uc_wants_guc(uc)),
>>   		yesno(intel_uc_wants_guc_submission(uc)),
>> -		yesno(intel_uc_wants_huc(uc)));
>> +		yesno(intel_uc_wants_huc(uc)),
>> +		yesno(intel_uc_wants_guc_slpc(uc)));
>>   
>>   	if (i915->params.enable_guc == 0) {
>>   		GEM_BUG_ON(intel_uc_wants_guc(uc));
>>   		GEM_BUG_ON(intel_uc_wants_guc_submission(uc));
>>   		GEM_BUG_ON(intel_uc_wants_huc(uc));
>> +		GEM_BUG_ON(intel_uc_wants_guc_slpc(uc));
>>   		return;
>>   	}
>>   
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.h b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
>> index e2da2b6e76e1..38e465fd8a0c 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
>> @@ -83,6 +83,7 @@ __uc_state_checker(x, func, uses, used)
>>   uc_state_checkers(guc, guc);
>>   uc_state_checkers(huc, huc);
>>   uc_state_checkers(guc, guc_submission);
>> +uc_state_checkers(guc, guc_slpc);
>>   
>>   #undef uc_state_checkers
>>   #undef __uc_state_checker
>>

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 02/16] drm/i915/guc/slpc: Initial definitions for slpc
  2021-07-10 14:27   ` Michal Wajdeczko
  2021-07-12 18:40     ` Belgaumkar, Vinay
@ 2021-07-12 23:43     ` Belgaumkar, Vinay
  1 sibling, 0 replies; 49+ messages in thread
From: Belgaumkar, Vinay @ 2021-07-12 23:43 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx, dri-devel
  Cc: Daniele Ceraolo Spurio, Sundaresan Sujaritha



On 7/10/2021 7:27 AM, Michal Wajdeczko wrote:
> Hi Vinay,
> 
> On 10.07.2021 03:20, Vinay Belgaumkar wrote:
>> Add macros to check for slpc support. This feature is currently supported
>> for gen12+ and enabled whenever guc submission is enabled/selected.
> 
> please try to use consistent names across all patches:
> 
> s/slpc/SLPC
> s/gen12/Gen12
> s/guc/GuC

Ok.

> 
>>
>> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
>> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>> ---
>>   drivers/gpu/drm/i915/gt/uc/intel_guc.c        |  1 +
>>   drivers/gpu/drm/i915/gt/uc/intel_guc.h        |  2 ++
>>   .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 21 +++++++++++++++++++
>>   .../gpu/drm/i915/gt/uc/intel_guc_submission.h | 16 ++++++++++++++
>>   drivers/gpu/drm/i915/gt/uc/intel_uc.c         |  6 ++++--
>>   drivers/gpu/drm/i915/gt/uc/intel_uc.h         |  1 +
>>   6 files changed, 45 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> index 979128e28372..b9a809f2d221 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> @@ -157,6 +157,7 @@ void intel_guc_init_early(struct intel_guc *guc)
>>   	intel_guc_ct_init_early(&guc->ct);
>>   	intel_guc_log_init_early(&guc->log);
>>   	intel_guc_submission_init_early(guc);
>> +	intel_guc_slpc_init_early(guc);
>>   
>>   	mutex_init(&guc->send_mutex);
>>   	spin_lock_init(&guc->irq_lock);
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
>> index 5d94cf482516..e5a456918b88 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
>> @@ -57,6 +57,8 @@ struct intel_guc {
>>   
>>   	bool submission_supported;
>>   	bool submission_selected;
>> +	bool slpc_supported;
>> +	bool slpc_selected;
>>   
>>   	struct i915_vma *ads_vma;
>>   	struct __guc_ads_blob *ads_blob;
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
>> index 9c102bf0c8e3..e2644a05f298 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
>> @@ -2351,6 +2351,27 @@ void intel_guc_submission_init_early(struct intel_guc *guc)
>>   	guc->submission_selected = __guc_submission_selected(guc);
>>   }
>>   
>> +static bool __guc_slpc_supported(struct intel_guc *guc)
> 
> hmm, easy to confuse with intel_guc_slpc_is_supported, so maybe:
> 
> __detect_slpc_supported()
> 
> (yes, I know you were following code above)
> 
>> +{
>> +	/* GuC slpc is unavailable for pre-Gen12 */
> 
> s/slpc/SLPC

  Ok.

> 
>> +	return guc->submission_supported &&
>> +		GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12;
>> +}
>> +
>> +static bool __guc_slpc_selected(struct intel_guc *guc)
>> +{
>> +	if (!intel_guc_slpc_is_supported(guc))
>> +		return false;
>> +
>> +	return guc->submission_selected;
>> +}
>> +
>> +void intel_guc_slpc_init_early(struct intel_guc *guc)
>> +{
>> +	guc->slpc_supported = __guc_slpc_supported(guc);
>> +	guc->slpc_selected = __guc_slpc_selected(guc);
>> +}
> 
> in patch 4/16 you are introducing intel_guc_slpc.c|h so to have proper
> encapsulation better to define this function as
> 
> void intel_guc_slpc_init_early(struct intel_guc_slpc *slpc) { }
> 
> and move it to intel_guc_slpc.c

done.

> 
>> +
>>   static inline struct intel_context *
>>   g2h_context_lookup(struct intel_guc *guc, u32 desc_idx)
>>   {
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
>> index be767eb6ff71..7ae5fd052faf 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
>> @@ -13,6 +13,7 @@
>>   struct drm_printer;
>>   struct intel_engine_cs;
>>   
>> +void intel_guc_slpc_init_early(struct intel_guc *guc);
> 
> it really does not belong to this .h
> 
>>   void intel_guc_submission_init_early(struct intel_guc *guc);
>>   int intel_guc_submission_init(struct intel_guc *guc);
>>   void intel_guc_submission_enable(struct intel_guc *guc);
>> @@ -50,4 +51,19 @@ static inline bool intel_guc_submission_is_used(struct intel_guc *guc)
>>   	return intel_guc_is_used(guc) && intel_guc_submission_is_wanted(guc);
>>   }
>>   
>> +static inline bool intel_guc_slpc_is_supported(struct intel_guc *guc)
>> +{
>> +	return guc->slpc_supported;
>> +}
>> +
>> +static inline bool intel_guc_slpc_is_wanted(struct intel_guc *guc)
>> +{
>> +	return guc->slpc_selected;
>> +}
>> +
>> +static inline bool intel_guc_slpc_is_used(struct intel_guc *guc)
>> +{
>> +	return intel_guc_submission_is_used(guc) && intel_guc_slpc_is_wanted(guc);
>> +}
> 
> did you try to define them in intel_guc_slpc.h ?
> 
> note that to avoid circular dependencies you can define slpc struct in
> intel_guc_slpc_types.h and then
> 
> in intel_guc.h:
> 	#include "intel_guc_slpc_types.h" instead of intel_guc_slpc.h
> 
> in intel_guc_slpc.h:
> 	#include "intel_guc.h"
> 	#include "intel_guc_slpc_types.h"
> 	#include "intel_guc_submission.h"
> 

that worked.

Thanks,
Vinay.

>> +
>>   #endif
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
>> index 61be0aa81492..dca5f6d0641b 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
>> @@ -76,16 +76,18 @@ static void __confirm_options(struct intel_uc *uc)
>>   	struct drm_i915_private *i915 = uc_to_gt(uc)->i915;
>>   
>>   	drm_dbg(&i915->drm,
>> -		"enable_guc=%d (guc:%s submission:%s huc:%s)\n",
>> +		"enable_guc=%d (guc:%s submission:%s huc:%s slpc:%s)\n",
>>   		i915->params.enable_guc,
>>   		yesno(intel_uc_wants_guc(uc)),
>>   		yesno(intel_uc_wants_guc_submission(uc)),
>> -		yesno(intel_uc_wants_huc(uc)));
>> +		yesno(intel_uc_wants_huc(uc)),
>> +		yesno(intel_uc_wants_guc_slpc(uc)));
>>   
>>   	if (i915->params.enable_guc == 0) {
>>   		GEM_BUG_ON(intel_uc_wants_guc(uc));
>>   		GEM_BUG_ON(intel_uc_wants_guc_submission(uc));
>>   		GEM_BUG_ON(intel_uc_wants_huc(uc));
>> +		GEM_BUG_ON(intel_uc_wants_guc_slpc(uc));
>>   		return;
>>   	}
>>   
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.h b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
>> index e2da2b6e76e1..38e465fd8a0c 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
>> @@ -83,6 +83,7 @@ __uc_state_checker(x, func, uses, used)
>>   uc_state_checkers(guc, guc);
>>   uc_state_checkers(huc, huc);
>>   uc_state_checkers(guc, guc_submission);
>> +uc_state_checkers(guc, guc_slpc);
>>   
>>   #undef uc_state_checkers
>>   #undef __uc_state_checker
>>

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Intel-gfx] [PATCH 04/16] drm/i915/guc/slpc: Lay out slpc init/enable/disable/fini
  2021-07-10 14:35   ` [Intel-gfx] " Michal Wajdeczko
@ 2021-07-13  0:37     ` Belgaumkar, Vinay
  0 siblings, 0 replies; 49+ messages in thread
From: Belgaumkar, Vinay @ 2021-07-13  0:37 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx, dri-devel



On 7/10/2021 7:35 AM, Michal Wajdeczko wrote:
> 
> 
> On 10.07.2021 03:20, Vinay Belgaumkar wrote:
>> Declare header and source files for SLPC, along with init and
>> enable/disable function templates.
> 
> later you claim that "disable" is not needed

Changed.

> 
>>
>> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
>> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
>> ---
>>   drivers/gpu/drm/i915/Makefile               |  1 +
>>   drivers/gpu/drm/i915/gt/uc/intel_guc.h      |  2 ++
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 34 +++++++++++++++++++++
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 16 ++++++++++
>>   4 files changed, 53 insertions(+)
>>   create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>>   create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>>
>> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
>> index ab7679957623..d8eac4468df9 100644
>> --- a/drivers/gpu/drm/i915/Makefile
>> +++ b/drivers/gpu/drm/i915/Makefile
>> @@ -186,6 +186,7 @@ i915-y += gt/uc/intel_uc.o \
>>   	  gt/uc/intel_guc_fw.o \
>>   	  gt/uc/intel_guc_log.o \
>>   	  gt/uc/intel_guc_log_debugfs.o \
>> +	  gt/uc/intel_guc_slpc.o \
>>   	  gt/uc/intel_guc_submission.o \
>>   	  gt/uc/intel_huc.o \
>>   	  gt/uc/intel_huc_debugfs.o \
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
>> index e5a456918b88..0dbbd9cf553f 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
>> @@ -15,6 +15,7 @@
>>   #include "intel_guc_ct.h"
>>   #include "intel_guc_log.h"
>>   #include "intel_guc_reg.h"
>> +#include "intel_guc_slpc.h"
>>   #include "intel_uc_fw.h"
>>   #include "i915_utils.h"
>>   #include "i915_vma.h"
>> @@ -30,6 +31,7 @@ struct intel_guc {
>>   	struct intel_uc_fw fw;
>>   	struct intel_guc_log log;
>>   	struct intel_guc_ct ct;
>> +	struct intel_guc_slpc slpc;
>>   
>>   	/* Global engine used to submit requests to GuC */
>>   	struct i915_sched_engine *sched_engine;
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> new file mode 100644
>> index 000000000000..c1f569d2300d
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> @@ -0,0 +1,34 @@
>> +/*
>> + * SPDX-License-Identifier: MIT
> 
> SPDX tag shall be in very first line, for .c:
> 
> // SPDX-License-Identifier: MIT
> 
>> + *
>> + * Copyright © 2020 Intel Corporation
> 
> 2021

done.

> 
>> + */
>> +
>> +#include "intel_guc_slpc.h"
>> +
>> +int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
>> +{
>> +	return 0;
>> +}
>> +
>> +/*
>> + * intel_guc_slpc_enable() - Start SLPC
>> + * @slpc: pointer to intel_guc_slpc.
>> + *
>> + * SLPC is enabled by setting up the shared data structure and
>> + * sending reset event to GuC SLPC. Initial data is setup in
>> + * intel_guc_slpc_init. Here we send the reset event. We do
>> + * not currently need a slpc_disable since this is taken care
>> + * of automatically when a reset/suspend occurs and the guc
> 
> s/guc/GuC
> 
>> + * channels are destroyed.
> 
> you mean CTB ?

yes, fixed.

> 
>> + *
>> + * Return: 0 on success, non-zero error code on failure.
>> + */
>> +int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
>> +{
>> +	return 0;
>> +}
>> +
>> +void intel_guc_slpc_fini(struct intel_guc_slpc *slpc)
>> +{
>> +}
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> new file mode 100644
>> index 000000000000..74fd86769163
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> @@ -0,0 +1,16 @@
>> +/*
>> + * SPDX-License-Identifier: MIT
> 
> SPDX tag shall be in very first line, for .h:
> 
> /* SPDX-License-Identifier: MIT */
> 
>> + *
>> + * Copyright © 2020 Intel Corporation
> 
> 2021
> 
>> + */
>> +#ifndef _INTEL_GUC_SLPC_H_
>> +#define _INTEL_GUC_SLPC_H_
>> +
>> +struct intel_guc_slpc {
>> +};
> 
> move all data definitions to intel_guc_slpc_types.h and include it here
> 
>> +
>> +int intel_guc_slpc_init(struct intel_guc_slpc *slpc);
>> +int intel_guc_slpc_enable(struct intel_guc_slpc *slpc);
>> +void intel_guc_slpc_fini(struct intel_guc_slpc *slpc);
>> +
>> +#endif
>>
> 
> and as suggested in comment to 2/14 you should likely move this patch to
> the front of the series

Yes, squashed with the first patch.

Thanks,
Vinay.

> 
> Michal
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 05/16] drm/i915/guc/slpc: Adding slpc communication interfaces
  2021-07-10 15:52   ` Michal Wajdeczko
@ 2021-07-13 23:22     ` Belgaumkar, Vinay
  0 siblings, 0 replies; 49+ messages in thread
From: Belgaumkar, Vinay @ 2021-07-13 23:22 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx, dri-devel; +Cc: Sundaresan Sujaritha



On 7/10/2021 8:52 AM, Michal Wajdeczko wrote:
> 
> 
> On 10.07.2021 03:20, Vinay Belgaumkar wrote:
>> Replicate the SLPC header file in GuC for the most part. There are
> 
> what you mean by "replicate" here?
> 
>> some SLPC mode based parameters which haven't been included since
>> we are not using them.
>>
>> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
>> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
>> ---
>>   drivers/gpu/drm/i915/gt/uc/intel_guc.c        |   4 +
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h   |   2 +
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h   |   2 +
>>   .../gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h  | 255 ++++++++++++++++++
>>   4 files changed, 263 insertions(+)
>>   create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h
>>
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> index b9a809f2d221..9d61b2d54de4 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> @@ -202,11 +202,15 @@ static u32 guc_ctl_debug_flags(struct intel_guc *guc)
>>   
>>   static u32 guc_ctl_feature_flags(struct intel_guc *guc)
>>   {
>> +	struct intel_gt *gt = guc_to_gt(guc);
>>   	u32 flags = 0;
>>   
>>   	if (!intel_guc_submission_is_used(guc))
>>   		flags |= GUC_CTL_DISABLE_SCHEDULER;
>>   
>> +	if (intel_uc_uses_guc_slpc(&gt->uc))
>> +		flags |= GUC_CTL_ENABLE_SLPC;
>> +
>>   	return flags;
>>   }
>>   
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
>> index 94bb1ca6f889..19e2504d7a36 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
>> @@ -114,6 +114,8 @@
>>   #define   GUC_ADS_ADDR_SHIFT		1
>>   #define   GUC_ADS_ADDR_MASK		(0xFFFFF << GUC_ADS_ADDR_SHIFT)
>>   
>> +#define GUC_CTL_ENABLE_SLPC            BIT(2)
> 
> this should be defined closer to GUC_CTL_FEATURE

done.

> 
>> +
>>   #define GUC_CTL_MAX_DWORDS		(SOFT_SCRATCH_COUNT - 2) /* [1..14] */
>>   
>>   /* Generic GT SysInfo data types */
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> index 74fd86769163..98036459a1a3 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> @@ -6,6 +6,8 @@
>>   #ifndef _INTEL_GUC_SLPC_H_
>>   #define _INTEL_GUC_SLPC_H_
>>   
>> +#include "intel_guc_slpc_fwif.h"
> 
> doesn't seem to be needed right now

Removed for this patch.
> 
>> +
>>   struct intel_guc_slpc {
>>   };
>>   
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h
>> new file mode 100644
>> index 000000000000..2a5e71428374
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h
> 
> I've started to move all pure ABI definitions to files in abi/ folder,
> leaving in guc_fwif.h only our next level helpers/wrappers.
> 
> Can you move these SLPC definition there too ? maybe as dedicated:
> 
> 	abi/guc_slpc_abi.h

done.

> 
>> @@ -0,0 +1,255 @@
>> +/*
>> + * SPDX-License-Identifier: MIT
> 
> use proper format
> 
>> + *
>> + * Copyright © 2020 Intel Corporation
> 
> 2021
> 
>> + */
>> +#ifndef _INTEL_GUC_SLPC_FWIF_H_
>> +#define _INTEL_GUC_SLPC_FWIF_H_
>> +
>> +#include <linux/types.h>
>> +
>> +/* This file replicates the header in GuC code for handling SLPC related
>> + * data structures and sizes
>> + */
> 
> use proper format for multi-line comments:
> 
> 	/*
> 	 * blah blah
> 	 * blah blah
> 	 */

done.

> 
>> +
>> +/* SLPC exposes certain parameters for global configuration by the host.
>> + * These are referred to as override parameters, because in most cases
>> + * the host will not need to modify the default values used by SLPC.
>> + * SLPC remembers the default values which allows the host to easily restore
>> + * them by simply unsetting the override. The host can set or unset override
>> + * parameters during SLPC (re-)initialization using the SLPC Reset event.
>> + * The host can also set or unset override parameters on the fly using the
>> + * Parameter Set and Parameter Unset events
>> + */
>> +#define SLPC_MAX_OVERRIDE_PARAMETERS	256
>> +#define SLPC_OVERRIDE_BITFIELD_SIZE \
>> +		(SLPC_MAX_OVERRIDE_PARAMETERS / 32)
>> +
>> +#define SLPC_PAGE_SIZE_BYTES			4096
>> +#define SLPC_CACHELINE_SIZE_BYTES		64
>> +#define SLPC_SHARE_DATA_SIZE_BYTE_HEADER	SLPC_CACHELINE_SIZE_BYTES
>> +#define SLPC_SHARE_DATA_SIZE_BYTE_PLATFORM_INFO	SLPC_CACHELINE_SIZE_BYTES
>> +#define SLPC_SHARE_DATA_SIZE_BYTE_TASK_STATE	SLPC_CACHELINE_SIZE_BYTES
>> +#define SLPC_SHARE_DATA_MODE_DEFN_TABLE_SIZE	SLPC_PAGE_SIZE_BYTES
> 
> can you put some simply diagram that would describe this layout ?

done for the shared data struct.

> 
>> +
>> +#define SLPC_SHARE_DATA_SIZE_BYTE_MAX		(2 * SLPC_PAGE_SIZE_BYTES)
>> +
>> +/* Cacheline size aligned (Total size needed for
>> + * SLPM_KMD_MAX_OVERRIDE_PARAMETERS=256 is 1088 bytes)
>> + */
>> +#define SLPC_SHARE_DATA_SIZE_BYTE_PARAM		(((((SLPC_MAX_OVERRIDE_PARAMETERS * 4) \
>> +						+ ((SLPC_MAX_OVERRIDE_PARAMETERS / 32) * 4)) \
>> +		+ (SLPC_CACHELINE_SIZE_BYTES-1)) / SLPC_CACHELINE_SIZE_BYTES)*SLPC_CACHELINE_SIZE_BYTES)
>> +
>> +#define SLPC_SHARE_DATA_SIZE_BYTE_OTHER		(SLPC_SHARE_DATA_SIZE_BYTE_MAX - \
>> +					(SLPC_SHARE_DATA_SIZE_BYTE_HEADER \
>> +					+ SLPC_SHARE_DATA_SIZE_BYTE_PLATFORM_INFO \
>> +					+ SLPC_SHARE_DATA_SIZE_BYTE_TASK_STATE \
>> +					+ SLPC_SHARE_DATA_SIZE_BYTE_PARAM \
>> +					+ SLPC_SHARE_DATA_MODE_DEFN_TABLE_SIZE))
>> +
>> +#define SLPC_EVENT(id, argc)			((u32)(id) << 8 | (argc))
>> +
>> +#define SLPC_PARAM_TASK_DEFAULT			0
>> +#define SLPC_PARAM_TASK_ENABLED			1
>> +#define SLPC_PARAM_TASK_DISABLED		2
>> +#define SLPC_PARAM_TASK_UNKNOWN			3
> 
> many values below are defined as enum, why these values are #defines ?
> 
> and is there any relation to these ones defined below (look similar)?

No, they are different, added an enum.

> 
>   +	SLPC_PARAM_TASK_ENABLE_GTPERF = 0,
>   +	SLPC_PARAM_TASK_DISABLE_GTPERF = 1,
>   +	SLPC_PARAM_TASK_ENABLE_BALANCER = 2,
>   +	SLPC_PARAM_TASK_DISABLE_BALANCER = 3,
>   +	SLPC_PARAM_TASK_ENABLE_DCC = 4,
>   +	SLPC_PARAM_TASK_DISABLE_DCC = 5,
> 
>> +
>> +enum slpc_status {
>> +	SLPC_STATUS_OK = 0,
>> +	SLPC_STATUS_ERROR = 1,
>> +	SLPC_STATUS_ILLEGAL_COMMAND = 2,
>> +	SLPC_STATUS_INVALID_ARGS = 3,
>> +	SLPC_STATUS_INVALID_PARAMS = 4,
>> +	SLPC_STATUS_INVALID_DATA = 5,
>> +	SLPC_STATUS_OUT_OF_RANGE = 6,
>> +	SLPC_STATUS_NOT_SUPPORTED = 7,
>> +	SLPC_STATUS_NOT_IMPLEMENTED = 8,
>> +	SLPC_STATUS_NO_DATA = 9,
>> +	SLPC_STATUS_EVENT_NOT_REGISTERED = 10,
>> +	SLPC_STATUS_REGISTER_LOCKED = 11,
>> +	SLPC_STATUS_TEMPORARILY_UNAVAILABLE = 12,
>> +	SLPC_STATUS_VALUE_ALREADY_SET = 13,
>> +	SLPC_STATUS_VALUE_ALREADY_UNSET = 14,
>> +	SLPC_STATUS_VALUE_NOT_CHANGED = 15,
>> +	SLPC_STATUS_MEMIO_ERROR = 16,
>> +	SLPC_STATUS_EVENT_QUEUED_REQ_DPC = 17,
>> +	SLPC_STATUS_EVENT_QUEUED_NOREQ_DPC = 18,
>> +	SLPC_STATUS_NO_EVENT_QUEUED = 19,
>> +	SLPC_STATUS_OUT_OF_SPACE = 20,
>> +	SLPC_STATUS_TIMEOUT = 21,
>> +	SLPC_STATUS_NO_LOCK = 22,
>> +	SLPC_STATUS_MAX
>> +};
>> +
>> +enum slpc_event_id {
>> +	SLPC_EVENT_RESET = 0,
>> +	SLPC_EVENT_SHUTDOWN = 1,
>> +	SLPC_EVENT_PLATFORM_INFO_CHANGE = 2,
>> +	SLPC_EVENT_DISPLAY_MODE_CHANGE = 3,
>> +	SLPC_EVENT_FLIP_COMPLETE = 4,
>> +	SLPC_EVENT_QUERY_TASK_STATE = 5,
>> +	SLPC_EVENT_PARAMETER_SET = 6,
>> +	SLPC_EVENT_PARAMETER_UNSET = 7,
>> +};
>> +
>> +enum slpc_param_id {
>> +	SLPC_PARAM_TASK_ENABLE_GTPERF = 0,
>> +	SLPC_PARAM_TASK_DISABLE_GTPERF = 1,
>> +	SLPC_PARAM_TASK_ENABLE_BALANCER = 2,
>> +	SLPC_PARAM_TASK_DISABLE_BALANCER = 3,
>> +	SLPC_PARAM_TASK_ENABLE_DCC = 4,
>> +	SLPC_PARAM_TASK_DISABLE_DCC = 5,
>> +	SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ = 6,
>> +	SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ = 7,
>> +	SLPC_PARAM_GLOBAL_MIN_GT_SLICE_FREQ_MHZ = 8,
>> +	SLPC_PARAM_GLOBAL_MAX_GT_SLICE_FREQ_MHZ = 9,
>> +	SLPC_PARAM_GTPERF_THRESHOLD_MAX_FPS = 10,
>> +	SLPC_PARAM_GLOBAL_DISABLE_GT_FREQ_MANAGEMENT = 11,
>> +	SLPC_PARAM_GTPERF_ENABLE_FRAMERATE_STALLING = 12,
>> +	SLPC_PARAM_GLOBAL_DISABLE_RC6_MODE_CHANGE = 13,
>> +	SLPC_PARAM_GLOBAL_OC_UNSLICE_FREQ_MHZ = 14,
>> +	SLPC_PARAM_GLOBAL_OC_SLICE_FREQ_MHZ = 15,
>> +	SLPC_PARAM_GLOBAL_ENABLE_IA_GT_BALANCING = 16,
>> +	SLPC_PARAM_GLOBAL_ENABLE_ADAPTIVE_BURST_TURBO = 17,
>> +	SLPC_PARAM_GLOBAL_ENABLE_EVAL_MODE = 18,
>> +	SLPC_PARAM_GLOBAL_ENABLE_BALANCER_IN_NON_GAMING_MODE = 19,
>> +	SLPC_PARAM_GLOBAL_RT_MODE_TURBO_FREQ_DELTA_MHZ = 20,
>> +	SLPC_PARAM_PWRGATE_RC_MODE = 21,
>> +	SLPC_PARAM_EDR_MODE_COMPUTE_TIMEOUT_MS = 22,
>> +	SLPC_PARAM_EDR_QOS_FREQ_MHZ = 23,
>> +	SLPC_PARAM_MEDIA_FF_RATIO_MODE = 24,
>> +	SLPC_PARAM_ENABLE_IA_FREQ_LIMITING = 25,
>> +	SLPC_PARAM_STRATEGIES = 26,
>> +	SLPC_PARAM_POWER_PROFILE = 27,
>> +	SLPC_IGNORE_EFFICIENT_FREQUENCY = 28,
> 
> no PARAM tag inside this enum name
> 
>> +	SLPC_MAX_PARAM = 32,
> 
> can we move this out of enum, maybe as standalone #define ?
> or remove it as doesn't seem to be useful at all

Added PARAM tag, it needs to be part of this.

> 
>> +};
>> +
>> +enum slpc_global_state {
>> +	SLPC_GLOBAL_STATE_NOT_RUNNING = 0,
>> +	SLPC_GLOBAL_STATE_INITIALIZING = 1,
>> +	SLPC_GLOBAL_STATE_RESETTING = 2,
>> +	SLPC_GLOBAL_STATE_RUNNING = 3,
>> +	SLPC_GLOBAL_STATE_SHUTTING_DOWN = 4,
>> +	SLPC_GLOBAL_STATE_ERROR = 5
>> +};
>> +
>> +enum slpc_platform_sku {
>> +	SLPC_PLATFORM_SKU_UNDEFINED = 0,
>> +	SLPC_PLATFORM_SKU_ULX = 1,
>> +	SLPC_PLATFORM_SKU_ULT = 2,
>> +	SLPC_PLATFORM_SKU_T = 3,
>> +	SLPC_PLATFORM_SKU_MOBL = 4,
>> +	SLPC_PLATFORM_SKU_DT = 5,
>> +	SLPC_PLATFORM_SKU_UNKNOWN = 6,
>> +};
>> +
>> +struct slpc_platform_info {
>> +	union {
>> +		u32 sku;  /**< SKU info */
>> +		struct {
>> +			u32 reserved:8;
>> +			u32 fused_slice_count:8;
>> +			u32 reserved1:16;
>> +		};
>> +	};
>> +        union
>> +	{
>> +		u32 bitfield2;       /**< IA capability info*/
>> +		struct {
>> +			u32 max_p0_freq_bins:8;
>> +			u32 p1_freq_bins:8;
>> +			u32 pe_freq_bins:8;
>> +			u32 pn_freq_bins:8;
>> +		};
>> +	};
>> +	u32 reserved2[2];
>> +} __packed;
> 
> I'm not a big fan of using C bitfields for interface definitions
> 
> can we switch to regular #defines and use FIELD_GET|PREP ?

Done.

> 
>> +
>> +struct slpc_task_state_data {
>> +	union {
>> +		u32 bitfield1;
>> +		struct {
>> +			u32 gtperf_task_active:1;
>> +			u32 gtperf_stall_possible:1;
>> +			u32 gtperf_gaming_mode:1;
>> +			u32 gtperf_target_fps:8;
>> +			u32 dcc_task_active:1;
>> +			u32 in_dcc:1;
>> +			u32 in_dct:1;
>> +			u32 freq_switch_active:1;
>> +			u32 ibc_enabled:1;
>> +			u32 ibc_active:1;
>> +			u32 pg1_enabled:1;
>> +			u32 pg1_active:1;
>> +		};
>> +	};
>> +	union {
>> +		u32 bitfield2;
>> +		struct {
>> +			u32 max_unslice_freq:8;
>> +			u32 min_unslice_freq:8;
>> +			u32 max_slice_freq:8;
>> +			u32 min_slice_freq:8;
>> +		};
>> +	};
>> +} __packed;
>> +
>> +struct slpc_shared_data {
>> +	union {
>> +		struct {
>> +			/* Total size in bytes of this buffer. */
>> +			u32 shared_data_size;
>> +			u32 global_state;
>> +			u32 display_data_addr;
>> +		};
> 
> below all structs are named, this one not, why ?
> 
>> +		unsigned char reserved_header[SLPC_SHARE_DATA_SIZE_BYTE_HEADER];
> 
> this could be just "u8"
> 
> and I assume all these "reserved" are in fact padding, no ?
> 
>> +	};
>> +
>> +	union {
>> +		struct slpc_platform_info platform_info;
>> +		unsigned char reserved_platform[SLPC_SHARE_DATA_SIZE_BYTE_PLATFORM_INFO];
>> +	};
> 
> maybe we can avoid these unions by declaring padding explicitly:
> 
> 	struct slpc_platform_info platform_info;
> 	u8 platform_info_pad[SLPC_SHARE_DATA_SIZE_BYTE_PLATFORM_INFO -
> 	                     sizeof(struct slpc_platform_info)];
> 
>> +
>> +	union {
>> +		struct slpc_task_state_data task_state_data;
>> +		unsigned char reserved_task_state[SLPC_SHARE_DATA_SIZE_BYTE_TASK_STATE];
>> +	};
>> +
>> +	union {
>> +		struct {
>> +		u32 override_params_set_bits[SLPC_OVERRIDE_BITFIELD_SIZE];
>> +		u32 override_params_values[SLPC_MAX_OVERRIDE_PARAMETERS];
>> +		};
>> +		unsigned char reserved_override_parameter[SLPC_SHARE_DATA_SIZE_BYTE_PARAM];
>> +	};
>> +
>> +	unsigned char reserved_other[SLPC_SHARE_DATA_SIZE_BYTE_OTHER];
>> +
>> +	/* PAGE 2 (4096 bytes), mode based parameter will be removed soon */
>> +	unsigned char reserved_mode_definition[4096];
>> +} __packed;
>> +
>> +enum slpc_reset_flags {
>> +	SLPC_RESET_FLAG_TDR_OCCURRED = (1 << 0)
>> +};
>> +
>> +#define SLPC_EVENT_MAX_INPUT_ARGS  9
>> +#define SLPC_EVENT_MAX_OUTPUT_ARGS 1
>> +
>> +union slpc_event_input_header {
>> +	u32 value;
>> +	struct {
>> +		u32 num_args:8;
>> +		u32 event_id:8;
>> +	};
>> +};
> 
> I guess earlier #define SLPC_EVENT is related to above
> can we keep related definitions together ?
> 
>> +
>> +struct slpc_event_input {
>> +	u32 h2g_action_id;
>> +	union slpc_event_input_header header;
>> +	u32 args[SLPC_EVENT_MAX_INPUT_ARGS];
>> +} __packed;
> 
> this looks like a attempt to define details of the
> INTEL_GUC_ACTION_SLPC_REQUEST HXG request message.
> 
> so maybe it can be moved to abi/guc_actions_slpc_abi.h ?
> best if you can define it in the same fashion as CTB registration one
> 

Moved all this to the slpc_abi file and removed the fwif file for now.

Thanks,
Vinay.

> Michal
> 
>> +
>> +#endif
>>

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 06/16] drm/i915/guc/slpc: Allocate, initialize and release slpc
  2021-07-10 16:05   ` Michal Wajdeczko
@ 2021-07-14  1:40     ` Belgaumkar, Vinay
  0 siblings, 0 replies; 49+ messages in thread
From: Belgaumkar, Vinay @ 2021-07-14  1:40 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx, dri-devel; +Cc: Sundaresan Sujaritha



On 7/10/2021 9:05 AM, Michal Wajdeczko wrote:
> 
> 
> On 10.07.2021 03:20, Vinay Belgaumkar wrote:
>> Allocate data structures for SLPC and functions for
>> initializing on host side.
>>
>> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
>> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
>> ---
>>   drivers/gpu/drm/i915/gt/uc/intel_guc.c      | 11 +++++++
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 36 ++++++++++++++++++++-
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 20 ++++++++++++
>>   3 files changed, 66 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> index 9d61b2d54de4..82863a9bc8e8 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> @@ -336,6 +336,12 @@ int intel_guc_init(struct intel_guc *guc)
>>   			goto err_ct;
>>   	}
>>   
>> +	if (intel_guc_slpc_is_used(guc)) {
>> +		ret = intel_guc_slpc_init(&guc->slpc);
>> +		if (ret)
>> +			goto err_submission;
>> +	}
>> +
>>   	/* now that everything is perma-pinned, initialize the parameters */
>>   	guc_init_params(guc);
>>   
>> @@ -346,6 +352,8 @@ int intel_guc_init(struct intel_guc *guc)
>>   
>>   	return 0;
>>   
>> +err_submission:
>> +	intel_guc_submission_fini(guc);
>>   err_ct:
>>   	intel_guc_ct_fini(&guc->ct);
>>   err_ads:
>> @@ -368,6 +376,9 @@ void intel_guc_fini(struct intel_guc *guc)
>>   
>>   	i915_ggtt_disable_guc(gt->ggtt);
>>   
>> +	if (intel_guc_slpc_is_used(guc))
>> +		intel_guc_slpc_fini(&guc->slpc);
>> +
>>   	if (intel_guc_submission_is_used(guc))
>>   		intel_guc_submission_fini(guc);
>>   
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> index c1f569d2300d..94e2f19951aa 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> @@ -4,11 +4,41 @@
>>    * Copyright © 2020 Intel Corporation
>>    */
>>   
>> +#include <asm/msr-index.h>
> 
> hmm, what exactly is needed from this header ?

Was being used in a previous version for MSR reads, removed.

> 
>> +
>> +#include "gt/intel_gt.h"
>> +#include "gt/intel_rps.h"
>> +
>> +#include "i915_drv.h"
>>   #include "intel_guc_slpc.h"
>> +#include "intel_pm.h"
>> +
>> +static inline struct intel_guc *slpc_to_guc(struct intel_guc_slpc *slpc)
>> +{
>> +	return container_of(slpc, struct intel_guc, slpc);
>> +}
>> +
>> +static int slpc_shared_data_init(struct intel_guc_slpc *slpc)
>> +{
>> +	struct intel_guc *guc = slpc_to_guc(slpc);
>> +	int err;
>> +	u32 size = PAGE_ALIGN(sizeof(struct slpc_shared_data));
> 
> move err decl here
> 
>> +
>> +	err = intel_guc_allocate_and_map_vma(guc, size, &slpc->vma, &slpc->vaddr);
>> +	if (unlikely(err)) {
>> +		DRM_ERROR("Failed to allocate slpc struct (err=%d)\n", err);
> 
> s/slpc/SLPC
> 
> and use drm_err instead
> and you may also want to print error as %pe

added.

> 
>> +		i915_vma_unpin_and_release(&slpc->vma, I915_VMA_RELEASE_MAP);
> 
> do you really need this ?

removed.
> 
>> +		return err;
>> +	}
>> +
>> +	return err;
>> +}
>>   
>>   int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
>>   {
>> -	return 0;
>> +	GEM_BUG_ON(slpc->vma);
>> +
>> +	return slpc_shared_data_init(slpc);
>>   }
>>   
>>   /*
>> @@ -31,4 +61,8 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
>>   
>>   void intel_guc_slpc_fini(struct intel_guc_slpc *slpc)
>>   {
>> +	if (!slpc->vma)
>> +		return;
>> +
>> +	i915_vma_unpin_and_release(&slpc->vma, I915_VMA_RELEASE_MAP);
>>   }
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> index 98036459a1a3..a2643b904165 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> @@ -3,12 +3,32 @@
>>    *
>>    * Copyright © 2020 Intel Corporation
>>    */
>> +
> 
> should be fixed in earlier patch
> 
>>   #ifndef _INTEL_GUC_SLPC_H_
>>   #define _INTEL_GUC_SLPC_H_
>>   
>> +#include <linux/mutex.h>
>>   #include "intel_guc_slpc_fwif.h"
>>   
>>   struct intel_guc_slpc {
>> +	/*Protects access to vma and SLPC actions */
> 
> hmm, missing mutex ;)

Removed.

> 
>> +	struct i915_vma *vma;
>> +	void *vaddr;
> 
> no need to be void, define it as ptr to slpc_shared_data
> 
>> +
>> +	/* platform frequency limits */
>> +	u32 min_freq;
>> +	u32 rp0_freq;
>> +	u32 rp1_freq;
>> +
>> +	/* frequency softlimits */
>> +	u32 min_freq_softlimit;
>> +	u32 max_freq_softlimit;
>> +
>> +	struct {
>> +		u32 param_id;
>> +		u32 param_value;
>> +		u32 param_override;
>> +	} debug;
> 
> can you add all these extra fields in patches which will need them?
> 
> Michal

Done.

Thanks,
Vinay.

> 
>>   };
>>   
>>   int intel_guc_slpc_init(struct intel_guc_slpc *slpc);
>>
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Intel-gfx] [PATCH 07/16] drm/i915/guc/slpc: Enable slpc and add related H2G events
  2021-07-10 17:37   ` [Intel-gfx] " Michal Wajdeczko
@ 2021-07-15  1:58     ` Belgaumkar, Vinay
  2021-07-21 17:36       ` Michal Wajdeczko
  0 siblings, 1 reply; 49+ messages in thread
From: Belgaumkar, Vinay @ 2021-07-15  1:58 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx, dri-devel



On 7/10/2021 10:37 AM, Michal Wajdeczko wrote:
> 
> 
> On 10.07.2021 03:20, Vinay Belgaumkar wrote:
>> Add methods for interacting with guc for enabling SLPC. Enable
>> SLPC after guc submission has been established. GuC load will
> 
> s/guc/GuC
> 
>> fail if SLPC cannot be successfully initialized. Add various
>> helper methods to set/unset the parameters for SLPC. They can
>> be set using h2g calls or directly setting bits in the shared
> 
> /h2g/H2G

done.
> 
>> data structure.
>>
>> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
>> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
>> ---
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c   | 221 ++++++++++++++++++
>>   .../gpu/drm/i915/gt/uc/intel_guc_submission.c |   4 -
>>   drivers/gpu/drm/i915/gt/uc/intel_uc.c         |  10 +
>>   3 files changed, 231 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> index 94e2f19951aa..e579408d1c19 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> @@ -18,6 +18,61 @@ static inline struct intel_guc *slpc_to_guc(struct intel_guc_slpc *slpc)
>>   	return container_of(slpc, struct intel_guc, slpc);
>>   }
>>   
>> +static inline struct intel_gt *slpc_to_gt(struct intel_guc_slpc *slpc)
>> +{
>> +	return guc_to_gt(slpc_to_guc(slpc));
>> +}
>> +
>> +static inline struct drm_i915_private *slpc_to_i915(struct intel_guc_slpc *slpc)
>> +{
>> +	return (slpc_to_gt(slpc))->i915;
>> +}
>> +
>> +static void slpc_mem_set_param(struct slpc_shared_data *data,
>> +				u32 id, u32 value)
>> +{
>> +	GEM_BUG_ON(id >= SLPC_MAX_OVERRIDE_PARAMETERS);
>> +	/* When the flag bit is set, corresponding value will be read
>> +	 * and applied by slpc.
> 
> fix format of multi-line comment
> s/slpc/SLPC

Done.

> 
>> +	 */
>> +	data->override_params_set_bits[id >> 5] |= (1 << (id % 32));
> 
> use __set_bit instead
> 
>> +	data->override_params_values[id] = value;
>> +}
>> +
>> +static void slpc_mem_unset_param(struct slpc_shared_data *data,
>> +				 u32 id)
>> +{
>> +	GEM_BUG_ON(id >= SLPC_MAX_OVERRIDE_PARAMETERS);
>> +	/* When the flag bit is unset, corresponding value will not be
>> +	 * read by slpc.
>> +	 */
>> +	data->override_params_set_bits[id >> 5] &= (~(1 << (id % 32)));
> 
> same here

Done.

> 
>> +	data->override_params_values[id] = 0;
>> +}
>> +
>> +static void slpc_mem_task_control(struct slpc_shared_data *data,
>> +				 u64 val, u32 enable_id, u32 disable_id)
> 
> hmm, u64 to pass simple tri-state flag ?
> 
>> +{
>> +	/* Enabling a param involves setting the enable_id
>> +	 * to 1 and disable_id to 0. Setting it to default
>> +	 * will unset both enable and disable ids and let
>> +	 * slpc choose it's default values.
> 
> fix format + s/slpc/SLPC
> 
>> +	 */
>> +	if (val == SLPC_PARAM_TASK_DEFAULT) {
>> +		/* set default */
>> +		slpc_mem_unset_param(data, enable_id);
>> +		slpc_mem_unset_param(data, disable_id);
>> +	} else if (val == SLPC_PARAM_TASK_ENABLED) {
>> +		/* set enable */
>> +		slpc_mem_set_param(data, enable_id, 1);
>> +		slpc_mem_set_param(data, disable_id, 0);
>> +	} else if (val == SLPC_PARAM_TASK_DISABLED) {
>> +		/* set disable */
>> +		slpc_mem_set_param(data, disable_id, 1);
>> +		slpc_mem_set_param(data, enable_id, 0);
>> +	}
> 
> maybe instead of SLPC_PARAM_TASK_* flags (that btw were confusing me
> earlier) you can define 3x small helpers:
> 
> static void slpc_mem_set_default(data, enable_id, disable_id);
> static void slpc_mem_set_enabled(data, enable_id, disable_id);
> static void slpc_mem_set_disabled(data, enable_id, disable_id);
>

Agree, done.

> 
>> +}
>> +
>>   static int slpc_shared_data_init(struct intel_guc_slpc *slpc)
>>   {
>>   	struct intel_guc *guc = slpc_to_guc(slpc);
>> @@ -34,6 +89,128 @@ static int slpc_shared_data_init(struct intel_guc_slpc *slpc)
>>   	return err;
>>   }
>>   
>> +/*
>> + * Send SLPC event to guc
>> + *
>> + */
>> +static int slpc_send(struct intel_guc_slpc *slpc,
>> +			struct slpc_event_input *input,
>> +			u32 in_len)
>> +{
>> +	struct intel_guc *guc = slpc_to_guc(slpc);
>> +	u32 *action;
>> +
>> +	action = (u32 *)input;
>> +	action[0] = INTEL_GUC_ACTION_SLPC_REQUEST;
> 
> why not just updating input->h2g_action_id ?

Removed this, using your suggestion below instead.

> 
>> +
>> +	return intel_guc_send(guc, action, in_len);
>> +}
>> +
>> +static bool slpc_running(struct intel_guc_slpc *slpc)
>> +{
>> +	struct slpc_shared_data *data;
>> +	u32 slpc_global_state;
>> +
>> +	GEM_BUG_ON(!slpc->vma);
>> +
>> +	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));
> 
> do you really need to flush all 8K of shared data?
> it looks that you only need single u32

sure.

> 
>> +	data = slpc->vaddr;
>> +
>> +	slpc_global_state = data->global_state;
>> +
>> +	return (data->global_state == SLPC_GLOBAL_STATE_RUNNING);
>> +}
>> +
>> +static int host2guc_slpc_query_task_state(struct intel_guc_slpc *slpc)
>> +{
>> +	struct intel_guc *guc = slpc_to_guc(slpc);
>> +	u32 shared_data_gtt_offset = intel_guc_ggtt_offset(guc, slpc->vma);
>> +	struct slpc_event_input data = {0};
>> +
>> +	data.header.value = SLPC_EVENT(SLPC_EVENT_QUERY_TASK_STATE, 2);
> 
> you defined header.num_args and header.event_id, don't want to use them?
> 
>> +	data.args[0] = shared_data_gtt_offset;
>> +	data.args[1] = 0;
>> +
>> +	return slpc_send(slpc, &data, 4);
> 
> magic 4
> 
>> +}
>> +
>> +static int slpc_read_task_state(struct intel_guc_slpc *slpc)
>> +{
>> +	return host2guc_slpc_query_task_state(slpc);
>> +}
> 
> hmm, all this looks complicated more than needed, why not just:
> 
> static int guc_action_slpc_query(struct intel_guc *guc, u32 offset)
> {
> 	u32 request[] = {
> 		INTEL_GUC_ACTION_SLPC_REQUEST,
> 		SLPC_EVENT(SLPC_EVENT_QUERY_TASK_STATE, 2),
> 		offset,
> 		0,
> 	};
> 	int err;
> 
> 	return intel_guc_send(guc, request, ARRAY_SIZE(request));
> }
> 
> static int slpc_query_task_state(struct intel_guc_slpc *slpc)
> {
> 	struct intel_guc *guc = slpc_to_guc(slpc);
> 	u32 offset = intel_guc_ggtt_offset(guc, slpc->vma);
> 
> 	return guc_action_slpc_query(guc, offset);
> }

Using this now, definitely simpler.

> 
> btw, there is little magic in H2G data, as only event enums were defined
> in slpc_fwif.h (or slpc_abi.h) but it looks that len and format of args
> depends on the actual event used

yes, it also expects the action and num_args in the same word.

> 
>> +
>> +static const char *slpc_state_stringify(enum slpc_global_state state)
>> +{
>> +	const char *str = NULL;
>> +
>> +	switch (state) {
>> +	case SLPC_GLOBAL_STATE_NOT_RUNNING:
>> +		str = "not running";
>> +		break;
>> +	case SLPC_GLOBAL_STATE_INITIALIZING:
>> +		str = "initializing";
>> +		break;
>> +	case SLPC_GLOBAL_STATE_RESETTING:
>> +		str = "resetting";
>> +		break;
>> +	case SLPC_GLOBAL_STATE_RUNNING:
>> +		str = "running";
>> +		break;
>> +	case SLPC_GLOBAL_STATE_SHUTTING_DOWN:
>> +		str = "shutting down";
>> +		break;
>> +	case SLPC_GLOBAL_STATE_ERROR:
>> +		str = "error";
>> +		break;
>> +	default:
>> +		str = "unknown";
>> +		break;
>> +	}
>> +
>> +	return str;
>> +}
>> +
>> +static const char *get_slpc_state(struct intel_guc_slpc *slpc)
> 
> lot of duplicated code with slpc_running()
> 
> maybe there should be:
> 	u32 slpc_get_state(slpc);
> 	bool slpc_is_running(slpc);
> 	const char *slpc_state_string(slpc);

Ok, makes sense.

> 
> 
>> +{
>> +	struct slpc_shared_data *data;
>> +	u32 slpc_global_state;
>> +
>> +	GEM_BUG_ON(!slpc->vma);
>> +
>> +	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));
>> +	data = slpc->vaddr;
>> +
>> +	slpc_global_state = data->global_state;
>> +
>> +	return slpc_state_stringify(slpc_global_state);
>> +}
>> +
>> +static int host2guc_slpc_reset(struct intel_guc_slpc *slpc)
>> +{
>> +	struct intel_guc *guc = slpc_to_guc(slpc);
>> +	u32 shared_data_gtt_offset = intel_guc_ggtt_offset(guc, slpc->vma);
>> +	struct slpc_event_input data = {0};
>> +	int ret;
>> +
>> +	data.header.value = SLPC_EVENT(SLPC_EVENT_RESET, 2);
>> +	data.args[0] = shared_data_gtt_offset;
>> +	data.args[1] = 0;
>> +
>> +	/* TODO: Hardcoded 4 needs define */
>> +	ret = slpc_send(slpc, &data, 4);
>> +
>> +	if (!ret) {
>> +		/* TODO: How long to Wait until SLPC is running */
> 
> do we know state transitions ?
> maybe there is no point in waiting for RUNNING if it is in ERROR or
> SHUTTING_DOWN ?

It goes from "resetting" to "running" apparently, but the transitions 
are too quick to bother trapping. Apparently it should transition within 
1ms or so, so 5ms polling (at 10us interval) wait does not seem that bad.

> 
>> +		if (wait_for(slpc_running(slpc), 5)) {
> 
> magic 5
ok.

> 
>> +			DRM_ERROR("SLPC not enabled! State = %s\n",
> 
> use drm_err
ok.

> 
>> +				  get_slpc_state(slpc));
>> +			return -EIO;
>> +		}
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>>   int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
>>   {
>>   	GEM_BUG_ON(slpc->vma);
>> @@ -56,6 +233,50 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
>>    */
>>   int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
>>   {
>> +	struct drm_i915_private *i915 = slpc_to_i915(slpc);
>> +	struct slpc_shared_data *data;
>> +	int ret;
>> +
>> +	GEM_BUG_ON(!slpc->vma);
>> +
>> +	memset(slpc->vaddr, 0, sizeof(struct slpc_shared_data));
>> +
>> +	data = slpc->vaddr;
>> +	data->shared_data_size = sizeof(struct slpc_shared_data);
>> +
>> +	/* Enable only GTPERF task, Disable others */
>> +	slpc_mem_task_control(data, SLPC_PARAM_TASK_ENABLED,
>> +				SLPC_PARAM_TASK_ENABLE_GTPERF,
>> +				SLPC_PARAM_TASK_DISABLE_GTPERF);
>> +
>> +	slpc_mem_task_control(data, SLPC_PARAM_TASK_DISABLED,
>> +				SLPC_PARAM_TASK_ENABLE_BALANCER,
>> +				SLPC_PARAM_TASK_DISABLE_BALANCER);
>> +
>> +	slpc_mem_task_control(data, SLPC_PARAM_TASK_DISABLED,
>> +				SLPC_PARAM_TASK_ENABLE_DCC,
>> +				SLPC_PARAM_TASK_DISABLE_DCC);
>> +
>> +	ret = host2guc_slpc_reset(slpc);
>> +	if (ret) {
>> +		drm_err(&i915->drm, "SLPC Reset event returned %d", ret);
> 
> you may want to print error as %pe

Not sure I understand why? I thought %pe was only for pointer errors?


> missing \n

> 
>> +		return -EIO;
>> +	}
>> +
>> +	DRM_INFO("SLPC state: %s\n", get_slpc_state(slpc));
> 
> use drm_info
> 
>> +
>> +	if (slpc_read_task_state(slpc))
>> +		drm_err(&i915->drm, "Unable to read task state data");
> 
> missing \n
> 
>> +
>> +	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));
>> +
>> +	/* min and max frequency limits being used by SLPC */
>> +	drm_info(&i915->drm, "SLPC min freq: %u Mhz, max is %u Mhz",
> 
> missing \n
> 
>> +			DIV_ROUND_CLOSEST(data->task_state_data.min_unslice_freq *
>> +				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER),
>> +			DIV_ROUND_CLOSEST(data->task_state_data.max_unslice_freq *
>> +				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER));
> 
> this info/code seems to be duplicated in patch 10/16
> maybe just call intel_guc_slpc_info() here once available ?

intel_guc_slpc_info() prints a lot of other info, just need to print the 
frequencies here.

> 
>> +
>>   	return 0;
>>   }
>>   
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
>> index e2644a05f298..3e76d4d5f7bb 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
>> @@ -2321,10 +2321,6 @@ void intel_guc_submission_enable(struct intel_guc *guc)
>>   
>>   void intel_guc_submission_disable(struct intel_guc *guc)
>>   {
>> -	struct intel_gt *gt = guc_to_gt(guc);
>> -
>> -	GEM_BUG_ON(gt->awake); /* GT should be parked first */
> 
> if not mistake, can you explain why it was removed ?

This was part of a different commit. The BUG_ON in 
disable_guc_submission was added with an assumption that it will be 
called only during driver unload and not expected to hold any GT PM 
references. Since this needs to be called from an error scenario during 
slpc enable, remove the BUG_ON. Do we need this as a separate commit?

> 
>> -
>>   	/* Note: By the time we're here, GuC may have already been reset */
>>   }
>>   
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
>> index dca5f6d0641b..7b6c767d3eb0 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
>> @@ -501,6 +501,14 @@ static int __uc_init_hw(struct intel_uc *uc)
>>   	if (intel_uc_uses_guc_submission(uc))
>>   		intel_guc_submission_enable(guc);
>>   
>> +	if (intel_uc_uses_guc_slpc(uc)) {
>> +		ret = intel_guc_slpc_enable(&guc->slpc);
>> +		if (ret)
>> +			goto err_submission;
>> +		drm_info(&i915->drm, "GuC SLPC %s\n",
>> +			 enableddisabled(intel_uc_uses_guc_slpc(uc)));
> 
> move this drm_info after below GuC report and/or modify to have:

yup, incorrect merge. Moved.

Thanks,
Vinay.

> 
> "GuC firmware path.bin version 1.0 loaded:yes"
> "GuC submission:enabled"
> "GuC SLPC:enabled"
> "HuC firmware path.bin version 1.0 authenticated:yes"
> 
> Michal
> 
>> +	}
>> +
>>   	drm_info(&i915->drm, "%s firmware %s version %u.%u %s:%s\n",
>>   		 intel_uc_fw_type_repr(INTEL_UC_FW_TYPE_GUC), guc->fw.path,
>>   		 guc->fw.major_ver_found, guc->fw.minor_ver_found,
>> @@ -521,6 +529,8 @@ static int __uc_init_hw(struct intel_uc *uc)
>>   	/*
>>   	 * We've failed to load the firmware :(
>>   	 */
>> +err_submission:
>> +	intel_guc_submission_disable(guc);
>>   err_log_capture:
>>   	__uc_capture_load_err_log(uc);
>>   err_out:
>>

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 08/16] drm/i915/guc/slpc: Add methods to set min/max frequency
  2021-07-10 17:47   ` Michal Wajdeczko
@ 2021-07-16 18:00     ` Belgaumkar, Vinay
  0 siblings, 0 replies; 49+ messages in thread
From: Belgaumkar, Vinay @ 2021-07-16 18:00 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx, dri-devel; +Cc: Sundaresan Sujaritha



On 7/10/2021 10:47 AM, Michal Wajdeczko wrote:
> 
> 
> On 10.07.2021 03:20, Vinay Belgaumkar wrote:
>> Add param set h2g helpers to set the min and max frequencies
>> for use by SLPC.
>>
>> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
>> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
>> ---
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 94 +++++++++++++++++++++
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h |  2 +
>>   2 files changed, 96 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> index e579408d1c19..19cb26479942 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> @@ -106,6 +106,19 @@ static int slpc_send(struct intel_guc_slpc *slpc,
>>   	return intel_guc_send(guc, action, in_len);
>>   }
>>   
>> +static int host2guc_slpc_set_param(struct intel_guc_slpc *slpc,
>> +				   u32 id, u32 value)
>> +{
>> +	struct slpc_event_input data = {0};
>> +
>> +	data.header.value = SLPC_EVENT(SLPC_EVENT_PARAMETER_SET, 2);
>> +	data.args[0] = id;
>> +	data.args[1] = value;
>> +
>> +	return slpc_send(slpc, &data, 4);
> 
> as suggested before, use of explicit function like:
> 
> static int guc_action_slpc_param(guc, u32 id, u32 value)
> {
> 	u32 request[] = {
> 		INTEL_GUC_ACTION_SLPC_REQUEST,
> 		SLPC_EVENT(SLPC_EVENT_PARAMETER_SET, 2),
> 		id,
> 		value,
> 	};
> 
> 	return intel_guc_send(guc, request, ARRAY_SIZE(request));
> }
> 
> will be simpler/cleaner

done.

> 
>> +}
>> +
>> +
>>   static bool slpc_running(struct intel_guc_slpc *slpc)
>>   {
>>   	struct slpc_shared_data *data;
>> @@ -134,6 +147,19 @@ static int host2guc_slpc_query_task_state(struct intel_guc_slpc *slpc)
>>   	return slpc_send(slpc, &data, 4);
>>   }
>>   
>> +static int slpc_set_param(struct intel_guc_slpc *slpc, u32 id, u32 value)
>> +{
>> +	struct drm_i915_private *i915 = slpc_to_i915(slpc);
>> +	GEM_BUG_ON(id >= SLPC_MAX_PARAM);
>> +
>> +	if (host2guc_slpc_set_param(slpc, id, value)) {
>> +		drm_err(&i915->drm, "Unable to set param %x", id);
> 
> missing \n
> what about printing value to be set ?
> what about printing send error %pe ?

done.

> 
>> +		return -EIO;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>>   static int slpc_read_task_state(struct intel_guc_slpc *slpc)
>>   {
>>   	return host2guc_slpc_query_task_state(slpc);
>> @@ -218,6 +244,74 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
>>   	return slpc_shared_data_init(slpc);
>>   }
>>   
>> +/**
>> + * intel_guc_slpc_max_freq_set() - Set max frequency limit for SLPC.
>> + * @slpc: pointer to intel_guc_slpc.
>> + * @val: encoded frequency
> 
> what's the encoding ?

It should just be frequency (MHz).

> 
>> + *
>> + * This function will invoke GuC SLPC action to update the max frequency
>> + * limit for slice and unslice.
>> + *
>> + * Return: 0 on success, non-zero error code on failure.
>> + */
>> +int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val)
>> +{
>> +	int ret;
>> +	struct drm_i915_private *i915 = slpc_to_i915(slpc);
>> +	intel_wakeref_t wakeref;
>> +
>> +	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
> 
> use can use with_intel_runtime_pm(rpm, wakeref)

Ok.
> 
>> +
>> +	ret = slpc_set_param(slpc,
>> +		       SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ,
>> +		       val);
>> +
>> +	if (ret) {
>> +		drm_err(&i915->drm,
>> +			"Set max frequency unslice returned %d", ret);
> 
> missing \n
> print error with %pe
> but slpc_set_param returns only -EIO ;(

I was done that way so the sysfs method that calls it gets a standard 
value. Will change that.

> 
>> +		ret = -EIO;
>> +		goto done;
>> +	}
>> +
>> +done:
>> +	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
>> +	return ret;
>> +}
>> +
>> +/**
>> + * intel_guc_slpc_min_freq_set() - Set min frequency limit for SLPC.
>> + * @slpc: pointer to intel_guc_slpc.
>> + * @val: encoded frequency
>> + *
>> + * This function will invoke GuC SLPC action to update the min frequency
>> + * limit.
>> + *
>> + * Return: 0 on success, non-zero error code on failure.
>> + */
>> +int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val)
>> +{
>> +	int ret;
>> +	struct intel_guc *guc = slpc_to_guc(slpc);
>> +	struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
>> +	intel_wakeref_t wakeref;
>> +
>> +	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
>> +
>> +	ret = slpc_set_param(slpc,
>> +		       SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
>> +		       val);
>> +	if (ret) {
>> +		drm_err(&i915->drm,
>> +			"Set min frequency for unslice returned %d", ret);
> 
> as above

done.
Thanks,

Vinay.
> 
> Michal
> 
>> +		ret = -EIO;
>> +		goto done;
>> +	}
>> +
>> +done:
>> +	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
>> +	return ret;
>> +}
>> +
>>   /*
>>    * intel_guc_slpc_enable() - Start SLPC
>>    * @slpc: pointer to intel_guc_slpc.
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> index a2643b904165..a473e1ea7c10 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> @@ -34,5 +34,7 @@ struct intel_guc_slpc {
>>   int intel_guc_slpc_init(struct intel_guc_slpc *slpc);
>>   int intel_guc_slpc_enable(struct intel_guc_slpc *slpc);
>>   void intel_guc_slpc_fini(struct intel_guc_slpc *slpc);
>> +int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val);
>> +int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val);
>>   
>>   #endif
>>

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Intel-gfx] [PATCH 12/16] drm/i915/guc/slpc: Cache platform frequency limits for slpc
  2021-07-10 18:15   ` [Intel-gfx] " Michal Wajdeczko
@ 2021-07-17 19:30     ` Belgaumkar, Vinay
  2021-07-20 23:05     ` Belgaumkar, Vinay
  1 sibling, 0 replies; 49+ messages in thread
From: Belgaumkar, Vinay @ 2021-07-17 19:30 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx, dri-devel



On 7/10/2021 11:15 AM, Michal Wajdeczko wrote:
> 
> 
> On 10.07.2021 03:20, Vinay Belgaumkar wrote:
>> Cache rp0, rp1 and rpn platform limits into slpc structure
>> for range checking while setting min/max frequencies.
>>
>> Also add "soft" limits which keep track of frequency changes
>> made from userland. These are initially set to platform min
>> and max.
>>
>> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
>> ---
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 41 +++++++++++++++++++++
>>   1 file changed, 41 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> index d32274cd1db7..6e978f27b7a6 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> @@ -86,6 +86,9 @@ static int slpc_shared_data_init(struct intel_guc_slpc *slpc)
>>   		return err;
>>   	}
>>   
>> +	slpc->max_freq_softlimit = 0;
>> +	slpc->min_freq_softlimit = 0;
> 
> as mentioned earlier, now it is time to introduce these fields in .h

ok.

> 
>> +
>>   	return err;
>>   }
>>   
>> @@ -384,6 +387,29 @@ void intel_guc_pm_intrmsk_enable(struct intel_gt *gt)
>>   			   GEN6_PMINTRMSK, pm_intrmsk_mbz, 0);
>>   }
>>   
>> +static int intel_guc_slpc_set_softlimits(struct intel_guc_slpc *slpc)
>> +{
>> +	int ret = 0;
>> +
>> +	/* Softlimits are initially equivalent to platform limits
>> +	 * unless they have deviated from defaults, in which case,
>> +	 * we retain the values and set min/max accordingly.
>> +	 */
>> +	if (!slpc->max_freq_softlimit)
>> +		slpc->max_freq_softlimit = slpc->rp0_freq;
>> +	else if (slpc->max_freq_softlimit != slpc->rp0_freq)
>> +		ret = intel_guc_slpc_set_max_freq(slpc,
>> +					slpc->max_freq_softlimit);
>> +
>> +	if (!slpc->min_freq_softlimit)
>> +		slpc->min_freq_softlimit = slpc->min_freq;
>> +	else if (slpc->min_freq_softlimit != slpc->min_freq)
>> +		ret = intel_guc_slpc_set_min_freq(slpc,
>> +					slpc->min_freq_softlimit);
>> +
>> +	return ret;
>> +}
>> +
>>   /*
>>    * intel_guc_slpc_enable() - Start SLPC
>>    * @slpc: pointer to intel_guc_slpc.
>> @@ -402,6 +428,7 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
>>   	struct drm_i915_private *i915 = slpc_to_i915(slpc);
>>   	struct slpc_shared_data *data;
>>   	int ret;
>> +	u32 rp_state_cap;
> 
> move up to keep "ret" last
done.

> 
>>   
>>   	GEM_BUG_ON(!slpc->vma);
>>   
>> @@ -445,6 +472,20 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
>>   			DIV_ROUND_CLOSEST(data->task_state_data.max_unslice_freq *
>>   				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER));
>>   
>> +	rp_state_cap = intel_uncore_read(i915->gt.uncore, GEN6_RP_STATE_CAP);
>> +
>> +	slpc->rp0_freq = ((rp_state_cap >> 0) & 0xff) * GT_FREQUENCY_MULTIPLIER;
>> +	slpc->min_freq = ((rp_state_cap >> 16) & 0xff) * GT_FREQUENCY_MULTIPLIER;
>> +	slpc->rp1_freq = ((rp_state_cap >> 8) & 0xff) * GT_FREQUENCY_MULTIPLIER;
> 
> we should have definitions for these bits and then we should be able to
> use REG_FIELD_GET

ok.

> 
>> +
>> +	if (intel_guc_slpc_set_softlimits(slpc))
>> +		drm_err(&i915->drm, "Unable to set softlimits");
> 
> missing \n
> maybe we can also print error ?

done.

> 
>> +
>> +	drm_info(&i915->drm,
>> +		 "Platform fused frequency values -  min: %u Mhz, max: %u Mhz",
> 
> missing \n
> double space before 'min'

done.

Thanks,
Vinay.
> 
> Michal
> 
>> +		 slpc->min_freq,
>> +		 slpc->rp0_freq);
>> +
>>   	return 0;
>>   }
>>   
>>

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 09/16] drm/i915/guc/slpc: Add get max/min freq hooks
  2021-07-10 17:52   ` Michal Wajdeczko
@ 2021-07-20 22:08     ` Belgaumkar, Vinay
  0 siblings, 0 replies; 49+ messages in thread
From: Belgaumkar, Vinay @ 2021-07-20 22:08 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx, dri-devel; +Cc: Sundaresan Sujaritha



On 7/10/2021 10:52 AM, Michal Wajdeczko wrote:
> 
> 
> On 10.07.2021 03:20, Vinay Belgaumkar wrote:
>> Add helpers to read the min/max frequency being used
>> by SLPC. This is done by send a h2g command which forces
> 
> s/h2g/H2G

done.

> 
>> SLPC to update the shared data struct which can then be
>> read.
>>
>> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
>> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
>> ---
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 58 +++++++++++++++++++++
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h |  2 +
>>   2 files changed, 60 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> index 19cb26479942..98a283d31734 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> @@ -278,6 +278,35 @@ int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val)
>>   	return ret;
>>   }
>>   
>> +int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val)
>> +{
>> +	struct slpc_shared_data *data;
>> +	intel_wakeref_t wakeref;
>> +	struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915;
>> +	int ret = 0;
>> +
>> +	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
>> +
>> +	/* Force GuC to update task data */
>> +	if (slpc_read_task_state(slpc)) {
>> +		DRM_ERROR("Unable to update task data");
> 
> use drm_err
> missing \n
> maybe this message could be moved to slpc_read_task_state ?

Done.

> 
>> +		ret = -EIO;
>> +		goto done;
>> +	}
>> +
>> +	GEM_BUG_ON(!slpc->vma);
>> +
>> +	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));
> 
> maybe this can also be part of slpc_read_task_state ?

Yup.

> 
>> +	data = slpc->vaddr;
>> +
>> +	*val = DIV_ROUND_CLOSEST(data->task_state_data.max_unslice_freq *
>> +				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER);
>> +
>> +done:
>> +	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
>> +	return ret;
>> +}
>> +
>>   /**
>>    * intel_guc_slpc_min_freq_set() - Set min frequency limit for SLPC.
>>    * @slpc: pointer to intel_guc_slpc.
>> @@ -312,6 +341,35 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val)
>>   	return ret;
>>   }
>>   
>> +int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val)
> 
> missing kernel-doc (above intel_guc_slpc_min_freq_set has one)

done.
> 
>> +{
>> +	struct slpc_shared_data *data;
>> +	intel_wakeref_t wakeref;
>> +	struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915;
>> +	int ret = 0;
>> +
>> +	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
>> +
>> +	/* Force GuC to update task data */
>> +	if (slpc_read_task_state(slpc)) {
>> +		DRM_ERROR("Unable to update task data");
> 
> see above
> 
>> +		ret = -EIO;
>> +		goto done;
>> +	}
>> +
>> +	GEM_BUG_ON(!slpc->vma);
>> +
>> +	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));
> 
> see above
Done.

Thanks,
Vinay.

> 
> Michal
> 
>> +	data = slpc->vaddr;
>> +
>> +	*val = DIV_ROUND_CLOSEST(data->task_state_data.min_unslice_freq *
>> +				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER);
>> +
>> +done:
>> +	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
>> +	return ret;
>> +}
>> +
>>   /*
>>    * intel_guc_slpc_enable() - Start SLPC
>>    * @slpc: pointer to intel_guc_slpc.
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> index a473e1ea7c10..2cb830cdacb5 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> @@ -36,5 +36,7 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc);
>>   void intel_guc_slpc_fini(struct intel_guc_slpc *slpc);
>>   int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val);
>>   int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val);
>> +int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val);
>> +int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val);
>>   
>>   #endif
>>

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 10/16] drm/i915/guc/slpc: Add debugfs for slpc info
  2021-07-10 18:08   ` Michal Wajdeczko
@ 2021-07-20 23:00     ` Belgaumkar, Vinay
  0 siblings, 0 replies; 49+ messages in thread
From: Belgaumkar, Vinay @ 2021-07-20 23:00 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx, dri-devel; +Cc: Sundaresan Sujaritha



On 7/10/2021 11:08 AM, Michal Wajdeczko wrote:
> 
> 
> On 10.07.2021 03:20, Vinay Belgaumkar wrote:
>> This prints out relevant SLPC info from the SLPC shared structure.
>>
>> We will send a h2g message which forces SLPC to update the
>> shared data structure with latest information before reading it.
>>
>> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
>> Signed-off-by: Sundaresan Sujaritha <sujaritha.sundaresan@intel.com>
>> ---
>>   .../gpu/drm/i915/gt/uc/intel_guc_debugfs.c    | 16 ++++++
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c   | 53 +++++++++++++++++++
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h   |  3 ++
>>   3 files changed, 72 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
>> index 9a03ff56e654..bef749e54601 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
>> @@ -12,6 +12,7 @@
>>   #include "gt/uc/intel_guc_ct.h"
>>   #include "gt/uc/intel_guc_ads.h"
>>   #include "gt/uc/intel_guc_submission.h"
>> +#include "gt/uc/intel_guc_slpc.h"
>>   
>>   static int guc_info_show(struct seq_file *m, void *data)
>>   {
>> @@ -50,11 +51,26 @@ static int guc_registered_contexts_show(struct seq_file *m, void *data)
>>   }
>>   DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_registered_contexts);
>>   
>> +static int guc_slpc_info_show(struct seq_file *m, void *unused)
>> +{
>> +	struct intel_guc *guc = m->private;
>> +	struct intel_guc_slpc *slpc = &guc->slpc;
>> +	struct drm_printer p = drm_seq_file_printer(m);
>> +
>> +	if (!intel_guc_slpc_is_used(guc))
>> +		return -ENODEV;
>> +
>> +	return intel_guc_slpc_info(slpc, &p);
>> +}
>> +
> 
> other entries don't have empty line here

Removed.

> 
>> +DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_slpc_info);
>> +
>>   void intel_guc_debugfs_register(struct intel_guc *guc, struct dentry *root)
>>   {
>>   	static const struct debugfs_gt_file files[] = {
>>   		{ "guc_info", &guc_info_fops, NULL },
>>   		{ "guc_registered_contexts", &guc_registered_contexts_fops, NULL },
>> +		{ "guc_slpc_info", &guc_slpc_info_fops, NULL},
> 
> IIRC last field is "eval" where maybe you could add your own to check if
> intel_guc_slpc_is_used() to avoid exposing this info if N/A
ok, added.

> 
>>   	};
>>   
>>   	if (!intel_guc_is_supported(guc))
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> index 98a283d31734..d179ba14ece6 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> @@ -432,6 +432,59 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
>>   	return 0;
>>   }
>>   
>> +int intel_guc_slpc_info(struct intel_guc_slpc *slpc, struct drm_printer *p)
>> +{
>> +	struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915;
>> +	struct slpc_shared_data *data;
>> +	struct slpc_platform_info *platform_info;
>> +	struct slpc_task_state_data *task_state_data;
>> +	intel_wakeref_t wakeref;
>> +	int ret = 0;
>> +
>> +	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
>> +
>> +	if (slpc_read_task_state(slpc)) {
>> +		ret = -EIO;
>> +		goto done;
>> +	}
>> +
>> +	GEM_BUG_ON(!slpc->vma);
>> +
>> +	drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data));
> 
> likely will go away if integrated into slpc_read_task_state

yup.

> 
>> +	data = slpc->vaddr;
>> +
>> +	platform_info = &data->platform_info;
> 
> is this used ?

no, removed.
> 
>> +	task_state_data = &data->task_state_data;
> 
> as it looks that you treat these sections separately, then maybe it
> would be cleaner to have:
> 
> static void print_global_data(*global_data, *p) {}
> static void print_platform_info(*platform_info, *p) {}
> static void print_task_state_data(*task_state_data, *p) {}

If we make these indivudal functions, we'll need to duplicate a lot
of code - like getting wakeref and reading task state. Better to keep
it all in one function instead. There is no other use case to print them
except for debugfs.

> 
>> +
>> +	drm_printf(p, "SLPC state: %s\n", slpc_state_stringify(data->global_state));
>> +	drm_printf(p, "\tgtperf task active: %d\n",
>> +			task_state_data->gtperf_task_active);
>> +	drm_printf(p, "\tdcc task active: %d\n",
>> +				task_state_data->dcc_task_active);
>> +	drm_printf(p, "\tin dcc: %d\n",
>> +				task_state_data->in_dcc);
>> +	drm_printf(p, "\tfreq switch active: %d\n",
>> +				task_state_data->freq_switch_active);
>> +	drm_printf(p, "\tibc enabled: %d\n",
>> +				task_state_data->ibc_enabled);
>> +	drm_printf(p, "\tibc active: %d\n",
>> +				task_state_data->ibc_active);
>> +	drm_printf(p, "\tpg1 enabled: %s\n",
>> +				yesno(task_state_data->pg1_enabled));
>> +	drm_printf(p, "\tpg1 active: %s\n",
>> +				yesno(task_state_data->pg1_active));
>> +	drm_printf(p, "\tmax freq: %dMHz\n",
>> +				DIV_ROUND_CLOSEST(data->task_state_data.max_unslice_freq *
>> +				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER));
>> +	drm_printf(p, "\tmin freq: %dMHz\n",
>> +				DIV_ROUND_CLOSEST(data->task_state_data.min_unslice_freq *
>> +				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER));
> 
> you defined task_state_data but in above 2 you're accessing it from data

Fixed.

Thanks,
Vinay.

> 
> Michal
> 
>> +
>> +done:
>> +	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
>> +	return ret;
>> +}
>> +
>>   void intel_guc_slpc_fini(struct intel_guc_slpc *slpc)
>>   {
>>   	if (!slpc->vma)
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> index 2cb830cdacb5..cd12c5f19f4b 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>> @@ -10,6 +10,8 @@
>>   #include <linux/mutex.h>
>>   #include "intel_guc_slpc_fwif.h"
>>   
>> +struct drm_printer;
>> +
>>   struct intel_guc_slpc {
>>   	/*Protects access to vma and SLPC actions */
>>   	struct i915_vma *vma;
>> @@ -38,5 +40,6 @@ int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val);
>>   int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val);
>>   int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val);
>>   int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val);
>> +int intel_guc_slpc_info(struct intel_guc_slpc *slpc, struct drm_printer *p);
>>   
>>   #endif
>>

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Intel-gfx] [PATCH 12/16] drm/i915/guc/slpc: Cache platform frequency limits for slpc
  2021-07-10 18:15   ` [Intel-gfx] " Michal Wajdeczko
  2021-07-17 19:30     ` Belgaumkar, Vinay
@ 2021-07-20 23:05     ` Belgaumkar, Vinay
  1 sibling, 0 replies; 49+ messages in thread
From: Belgaumkar, Vinay @ 2021-07-20 23:05 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx, dri-devel



On 7/10/2021 11:15 AM, Michal Wajdeczko wrote:
> 
> 
> On 10.07.2021 03:20, Vinay Belgaumkar wrote:
>> Cache rp0, rp1 and rpn platform limits into slpc structure
>> for range checking while setting min/max frequencies.
>>
>> Also add "soft" limits which keep track of frequency changes
>> made from userland. These are initially set to platform min
>> and max.
>>
>> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
>> ---
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 41 +++++++++++++++++++++
>>   1 file changed, 41 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> index d32274cd1db7..6e978f27b7a6 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> @@ -86,6 +86,9 @@ static int slpc_shared_data_init(struct intel_guc_slpc *slpc)
>>   		return err;
>>   	}
>>   
>> +	slpc->max_freq_softlimit = 0;
>> +	slpc->min_freq_softlimit = 0;
> 
> as mentioned earlier, now it is time to introduce these fields in .h

done.

> 
>> +
>>   	return err;
>>   }
>>   
>> @@ -384,6 +387,29 @@ void intel_guc_pm_intrmsk_enable(struct intel_gt *gt)
>>   			   GEN6_PMINTRMSK, pm_intrmsk_mbz, 0);
>>   }
>>   
>> +static int intel_guc_slpc_set_softlimits(struct intel_guc_slpc *slpc)
>> +{
>> +	int ret = 0;
>> +
>> +	/* Softlimits are initially equivalent to platform limits
>> +	 * unless they have deviated from defaults, in which case,
>> +	 * we retain the values and set min/max accordingly.
>> +	 */
>> +	if (!slpc->max_freq_softlimit)
>> +		slpc->max_freq_softlimit = slpc->rp0_freq;
>> +	else if (slpc->max_freq_softlimit != slpc->rp0_freq)
>> +		ret = intel_guc_slpc_set_max_freq(slpc,
>> +					slpc->max_freq_softlimit);
>> +
>> +	if (!slpc->min_freq_softlimit)
>> +		slpc->min_freq_softlimit = slpc->min_freq;
>> +	else if (slpc->min_freq_softlimit != slpc->min_freq)
>> +		ret = intel_guc_slpc_set_min_freq(slpc,
>> +					slpc->min_freq_softlimit);
>> +
>> +	return ret;
>> +}
>> +
>>   /*
>>    * intel_guc_slpc_enable() - Start SLPC
>>    * @slpc: pointer to intel_guc_slpc.
>> @@ -402,6 +428,7 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
>>   	struct drm_i915_private *i915 = slpc_to_i915(slpc);
>>   	struct slpc_shared_data *data;
>>   	int ret;
>> +	u32 rp_state_cap;
> 
> move up to keep "ret" last

Done.

> 
>>   
>>   	GEM_BUG_ON(!slpc->vma);
>>   
>> @@ -445,6 +472,20 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
>>   			DIV_ROUND_CLOSEST(data->task_state_data.max_unslice_freq *
>>   				GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER));
>>   
>> +	rp_state_cap = intel_uncore_read(i915->gt.uncore, GEN6_RP_STATE_CAP);
>> +
>> +	slpc->rp0_freq = ((rp_state_cap >> 0) & 0xff) * GT_FREQUENCY_MULTIPLIER;
>> +	slpc->min_freq = ((rp_state_cap >> 16) & 0xff) * GT_FREQUENCY_MULTIPLIER;
>> +	slpc->rp1_freq = ((rp_state_cap >> 8) & 0xff) * GT_FREQUENCY_MULTIPLIER;
> 
> we should have definitions for these bits and then we should be able to
> use REG_FIELD_GET

done.

> 
>> +
>> +	if (intel_guc_slpc_set_softlimits(slpc))
>> +		drm_err(&i915->drm, "Unable to set softlimits");
> 
> missing \n
> maybe we can also print error ?

done.

> 
>> +
>> +	drm_info(&i915->drm,
>> +		 "Platform fused frequency values -  min: %u Mhz, max: %u Mhz",
> 
> missing \n
> double space before 'min'

done.

Thanks,
Vinay.
> 
> Michal
> 
>> +		 slpc->min_freq,
>> +		 slpc->rp0_freq);
>> +
>>   	return 0;
>>   }
>>   
>>

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc
  2021-07-10 18:20   ` Michal Wajdeczko
@ 2021-07-20 23:38     ` Belgaumkar, Vinay
  0 siblings, 0 replies; 49+ messages in thread
From: Belgaumkar, Vinay @ 2021-07-20 23:38 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx, dri-devel
  Cc: Tvrtko Ursulin, Sujaritha Sundaresan



On 7/10/2021 11:20 AM, Michal Wajdeczko wrote:
> 
> 
> On 10.07.2021 03:20, Vinay Belgaumkar wrote:
>> Update the get/set min/max freq hooks to work for
>> slpc case as well. Consolidate helpers for requested/min/max
>> frequency get/set to intel_rps where the proper action can
>> be taken depending on whether slpc is enabled.
> 
> 2x s/slpc/SLPC

done.
> 
>>
>> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
>> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
>> Signed-off-by: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
>> ---
>>   drivers/gpu/drm/i915/gt/intel_rps.c | 135 ++++++++++++++++++++++++++++
>>   drivers/gpu/drm/i915/gt/intel_rps.h |   5 ++
>>   drivers/gpu/drm/i915/i915_pmu.c     |   2 +-
>>   drivers/gpu/drm/i915/i915_reg.h     |   2 +
>>   drivers/gpu/drm/i915/i915_sysfs.c   |  71 +++------------
>>   5 files changed, 154 insertions(+), 61 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c
>> index e858eeb2c59d..88ffc5d90730 100644
>> --- a/drivers/gpu/drm/i915/gt/intel_rps.c
>> +++ b/drivers/gpu/drm/i915/gt/intel_rps.c
>> @@ -37,6 +37,12 @@ static struct intel_uncore *rps_to_uncore(struct intel_rps *rps)
>>   	return rps_to_gt(rps)->uncore;
>>   }
>>   
>> +static struct intel_guc_slpc *rps_to_slpc(struct intel_rps *rps)
>> +{
>> +	struct intel_gt *gt = rps_to_gt(rps);
>> +	return &gt->uc.guc.slpc;
> 
> either add empty line between decl/code or make it one-liner

done.

> 
>> +}
>> +
>>   static bool rps_uses_slpc(struct intel_rps *rps)
>>   {
>>   	struct intel_gt *gt = rps_to_gt(rps);
>> @@ -1960,6 +1966,135 @@ u32 intel_rps_read_actual_frequency(struct intel_rps *rps)
>>   	return freq;
>>   }
>>   
>> +u32 intel_rps_read_punit_req(struct intel_rps *rps)
>> +{
>> +	struct intel_uncore *uncore = rps_to_uncore(rps);
>> +
> 
> drop empty line

done.
> 
>> +	u32 pureq = intel_uncore_read(uncore, GEN6_RPNSWREQ);
>> +
>> +	return pureq;
>> +}
>> +
>> +u32 intel_rps_get_req(struct intel_rps *rps, u32 pureq)
>> +{
>> +	u32 req = pureq >> GEN9_SW_REQ_UNSLICE_RATIO_SHIFT;
>> +
>> +	return req;
>> +}
>> +
>> +u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps)
>> +{
>> +	u32 freq = intel_rps_get_req(rps, intel_rps_read_punit_req(rps));
>> +
>> +	return intel_gpu_freq(rps, freq);
>> +}
>> +
>> +u32 intel_rps_get_requested_frequency(struct intel_rps *rps)
>> +{
>> +	if (rps_uses_slpc(rps))
>> +		return intel_rps_read_punit_req_frequency(rps);
>> +	else
>> +		return intel_gpu_freq(rps, rps->cur_freq);
>> +}
>> +
>> +u32 intel_rps_get_max_frequency(struct intel_rps *rps)
>> +{
>> +	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
>> +
>> +	if (rps_uses_slpc(rps))
>> +		return slpc->max_freq_softlimit;
>> +	else
>> +		return intel_gpu_freq(rps, rps->max_freq_softlimit);
>> +}
>> +
>> +int intel_rps_set_max_frequency(struct intel_rps *rps, u32 val)
>> +{
>> +	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
>> +	int ret;
>> +
>> +	if (rps_uses_slpc(rps))
>> +		return intel_guc_slpc_set_max_freq(slpc, val);
>> +
>> +	mutex_lock(&rps->lock);
>> +
>> +	val = intel_freq_opcode(rps, val);
>> +	if (val < rps->min_freq ||
>> +	    val > rps->max_freq ||
>> +	    val < rps->min_freq_softlimit) {
>> +		ret = -EINVAL;
>> +		goto unlock;
>> +	}
>> +
>> +	if (val > rps->rp0_freq)
>> +		DRM_DEBUG("User requested overclocking to %d\n",
> 
> use drm_dbg

Done.

Thanks,
Vinay.
> 
> Michal
> 
>> +			  intel_gpu_freq(rps, val));
>> +
>> +	rps->max_freq_softlimit = val;
>> +
>> +	val = clamp_t(int, rps->cur_freq,
>> +		      rps->min_freq_softlimit,
>> +		      rps->max_freq_softlimit);
>> +
>> +	/*
>> +	 * We still need *_set_rps to process the new max_delay and
>> +	 * update the interrupt limits and PMINTRMSK even though
>> +	 * frequency request may be unchanged.
>> +	 */
>> +	intel_rps_set(rps, val);
>> +
>> +unlock:
>> +	mutex_unlock(&rps->lock);
>> +
>> +	return ret;
>> +}
>> +
>> +u32 intel_rps_get_min_frequency(struct intel_rps *rps)
>> +{
>> +	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
>> +
>> +	if (rps_uses_slpc(rps))
>> +		return slpc->min_freq_softlimit;
>> +	else
>> +		return intel_gpu_freq(rps, rps->min_freq_softlimit);
>> +}
>> +
>> +int intel_rps_set_min_frequency(struct intel_rps *rps, u32 val)
>> +{
>> +	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
>> +	int ret;
>> +
>> +	if (rps_uses_slpc(rps))
>> +		return intel_guc_slpc_set_min_freq(slpc, val);
>> +
>> +	mutex_lock(&rps->lock);
>> +
>> +	val = intel_freq_opcode(rps, val);
>> +	if (val < rps->min_freq ||
>> +	    val > rps->max_freq ||
>> +	    val > rps->max_freq_softlimit) {
>> +		ret = -EINVAL;
>> +		goto unlock;
>> +	}
>> +
>> +	rps->min_freq_softlimit = val;
>> +
>> +	val = clamp_t(int, rps->cur_freq,
>> +		      rps->min_freq_softlimit,
>> +		      rps->max_freq_softlimit);
>> +
>> +	/*
>> +	 * We still need *_set_rps to process the new min_delay and
>> +	 * update the interrupt limits and PMINTRMSK even though
>> +	 * frequency request may be unchanged.
>> +	 */
>> +	intel_rps_set(rps, val);
>> +
>> +unlock:
>> +	mutex_unlock(&rps->lock);
>> +
>> +	return ret;
>> +}
>> +
>>   /* External interface for intel_ips.ko */
>>   
>>   static struct drm_i915_private __rcu *ips_mchdev;
>> diff --git a/drivers/gpu/drm/i915/gt/intel_rps.h b/drivers/gpu/drm/i915/gt/intel_rps.h
>> index 1d2cfc98b510..9a09ff5ebf64 100644
>> --- a/drivers/gpu/drm/i915/gt/intel_rps.h
>> +++ b/drivers/gpu/drm/i915/gt/intel_rps.h
>> @@ -31,6 +31,11 @@ int intel_gpu_freq(struct intel_rps *rps, int val);
>>   int intel_freq_opcode(struct intel_rps *rps, int val);
>>   u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat1);
>>   u32 intel_rps_read_actual_frequency(struct intel_rps *rps);
>> +u32 intel_rps_get_requested_frequency(struct intel_rps *rps);
>> +u32 intel_rps_get_min_frequency(struct intel_rps *rps);
>> +int intel_rps_set_min_frequency(struct intel_rps *rps, u32 val);
>> +u32 intel_rps_get_max_frequency(struct intel_rps *rps);
>> +int intel_rps_set_max_frequency(struct intel_rps *rps, u32 val);
>>   
>>   void gen5_rps_irq_handler(struct intel_rps *rps);
>>   void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir);
>> diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c
>> index 34d37d46a126..a896bec18255 100644
>> --- a/drivers/gpu/drm/i915/i915_pmu.c
>> +++ b/drivers/gpu/drm/i915/i915_pmu.c
>> @@ -407,7 +407,7 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns)
>>   
>>   	if (pmu->enable & config_mask(I915_PMU_REQUESTED_FREQUENCY)) {
>>   		add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_REQ],
>> -				intel_gpu_freq(rps, rps->cur_freq),
>> +				intel_rps_get_requested_frequency(rps),
>>   				period_ns / 1000);
>>   	}
>>   
>> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
>> index 7d9e90aa3ec0..8ab3c2f8f8e4 100644
>> --- a/drivers/gpu/drm/i915/i915_reg.h
>> +++ b/drivers/gpu/drm/i915/i915_reg.h
>> @@ -9195,6 +9195,8 @@ enum {
>>   #define   GEN9_FREQUENCY(x)			((x) << 23)
>>   #define   GEN6_OFFSET(x)			((x) << 19)
>>   #define   GEN6_AGGRESSIVE_TURBO			(0 << 15)
>> +#define   GEN9_SW_REQ_UNSLICE_RATIO_SHIFT 	23
>> +
>>   #define GEN6_RC_VIDEO_FREQ			_MMIO(0xA00C)
>>   #define GEN6_RC_CONTROL				_MMIO(0xA090)
>>   #define   GEN6_RC_CTL_RC6pp_ENABLE		(1 << 16)
>> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
>> index 873bf996ceb5..f2eee8491b19 100644
>> --- a/drivers/gpu/drm/i915/i915_sysfs.c
>> +++ b/drivers/gpu/drm/i915/i915_sysfs.c
>> @@ -272,7 +272,7 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
>>   	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
>>   	struct intel_rps *rps = &i915->gt.rps;
>>   
>> -	return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->cur_freq));
>> +	return sysfs_emit(buf, "%d\n", intel_rps_get_requested_frequency(rps));
>>   }
>>   
>>   static ssize_t gt_boost_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
>> @@ -326,9 +326,10 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev,
>>   static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
>>   {
>>   	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
>> -	struct intel_rps *rps = &dev_priv->gt.rps;
>> +	struct intel_gt *gt = &dev_priv->gt;
>> +	struct intel_rps *rps = &gt->rps;
>>   
>> -	return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->max_freq_softlimit));
>> +	return sysfs_emit(buf, "%d\n", intel_rps_get_max_frequency(rps));
>>   }
>>   
>>   static ssize_t gt_max_freq_mhz_store(struct device *kdev,
>> @@ -336,7 +337,8 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
>>   				     const char *buf, size_t count)
>>   {
>>   	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
>> -	struct intel_rps *rps = &dev_priv->gt.rps;
>> +	struct intel_gt *gt = &dev_priv->gt;
>> +	struct intel_rps *rps = &gt->rps;
>>   	ssize_t ret;
>>   	u32 val;
>>   
>> @@ -344,35 +346,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
>>   	if (ret)
>>   		return ret;
>>   
>> -	mutex_lock(&rps->lock);
>> -
>> -	val = intel_freq_opcode(rps, val);
>> -	if (val < rps->min_freq ||
>> -	    val > rps->max_freq ||
>> -	    val < rps->min_freq_softlimit) {
>> -		ret = -EINVAL;
>> -		goto unlock;
>> -	}
>> -
>> -	if (val > rps->rp0_freq)
>> -		DRM_DEBUG("User requested overclocking to %d\n",
>> -			  intel_gpu_freq(rps, val));
>> -
>> -	rps->max_freq_softlimit = val;
>> -
>> -	val = clamp_t(int, rps->cur_freq,
>> -		      rps->min_freq_softlimit,
>> -		      rps->max_freq_softlimit);
>> -
>> -	/*
>> -	 * We still need *_set_rps to process the new max_delay and
>> -	 * update the interrupt limits and PMINTRMSK even though
>> -	 * frequency request may be unchanged.
>> -	 */
>> -	intel_rps_set(rps, val);
>> -
>> -unlock:
>> -	mutex_unlock(&rps->lock);
>> +	ret = intel_rps_set_max_frequency(rps, val);
>>   
>>   	return ret ?: count;
>>   }
>> @@ -380,9 +354,10 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
>>   static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
>>   {
>>   	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
>> -	struct intel_rps *rps = &dev_priv->gt.rps;
>> +	struct intel_gt *gt = &dev_priv->gt;
>> +	struct intel_rps *rps = &gt->rps;
>>   
>> -	return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->min_freq_softlimit));
>> +	return sysfs_emit(buf, "%d\n", intel_rps_get_min_frequency(rps));
>>   }
>>   
>>   static ssize_t gt_min_freq_mhz_store(struct device *kdev,
>> @@ -398,31 +373,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
>>   	if (ret)
>>   		return ret;
>>   
>> -	mutex_lock(&rps->lock);
>> -
>> -	val = intel_freq_opcode(rps, val);
>> -	if (val < rps->min_freq ||
>> -	    val > rps->max_freq ||
>> -	    val > rps->max_freq_softlimit) {
>> -		ret = -EINVAL;
>> -		goto unlock;
>> -	}
>> -
>> -	rps->min_freq_softlimit = val;
>> -
>> -	val = clamp_t(int, rps->cur_freq,
>> -		      rps->min_freq_softlimit,
>> -		      rps->max_freq_softlimit);
>> -
>> -	/*
>> -	 * We still need *_set_rps to process the new min_delay and
>> -	 * update the interrupt limits and PMINTRMSK even though
>> -	 * frequency request may be unchanged.
>> -	 */
>> -	intel_rps_set(rps, val);
>> -
>> -unlock:
>> -	mutex_unlock(&rps->lock);
>> +	ret = intel_rps_set_min_frequency(rps, val);
>>   
>>   	return ret ?: count;
>>   }
>>

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 15/16] drm/i915/guc/slpc: slpc selftest
  2021-07-10 18:29   ` Michal Wajdeczko
@ 2021-07-21  1:06     ` Belgaumkar, Vinay
  0 siblings, 0 replies; 49+ messages in thread
From: Belgaumkar, Vinay @ 2021-07-21  1:06 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx, dri-devel



On 7/10/2021 11:29 AM, Michal Wajdeczko wrote:
> 
> 
> On 10.07.2021 03:20, Vinay Belgaumkar wrote:
>> Tests that exercise the slpc get/set frequency interfaces.
>>
>> Clamp_max will set max frequency to multiple levels and check
>> that slpc requests frequency lower than or equal to it.
>>
>> Clamp_min will set min frequency to different levels and check
>> if slpc requests are higher or equal to those levels.
> 
> 2x s/slpc/SLPC

Done.

> 
>>
>> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
>> ---
>>   drivers/gpu/drm/i915/gt/intel_rps.c           |   1 +
>>   drivers/gpu/drm/i915/gt/selftest_slpc.c       | 333 ++++++++++++++++++
>>   drivers/gpu/drm/i915/gt/selftest_slpc.h       |  12 +
>>   .../drm/i915/selftests/i915_live_selftests.h  |   1 +
>>   4 files changed, 347 insertions(+)
>>   create mode 100644 drivers/gpu/drm/i915/gt/selftest_slpc.c
>>   create mode 100644 drivers/gpu/drm/i915/gt/selftest_slpc.h
>>
>> diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c
>> index 88ffc5d90730..16ac2e840881 100644
>> --- a/drivers/gpu/drm/i915/gt/intel_rps.c
>> +++ b/drivers/gpu/drm/i915/gt/intel_rps.c
>> @@ -2288,4 +2288,5 @@ EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
>>   
>>   #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
>>   #include "selftest_rps.c"
>> +#include "selftest_slpc.c"
>>   #endif
>> diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c b/drivers/gpu/drm/i915/gt/selftest_slpc.c
>> new file mode 100644
>> index 000000000000..f440c1cb2afa
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c
>> @@ -0,0 +1,333 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright © 2020 Intel Corporation
> 
> 2021

Done.

> 
>> + */
>> +#include "selftest_slpc.h"
>> +#include "selftest_rps.h"
>> +
>> +#include <linux/pm_qos.h>
>> +#include <linux/sort.h>
> 
> system headers should go first

Cleaned up and removed the unwanted headers.

> 
>> +
>> +#include "intel_engine_heartbeat.h"
>> +#include "intel_engine_pm.h"
>> +#include "intel_gpu_commands.h"
>> +#include "intel_gt_clock_utils.h"
>> +#include "intel_gt_pm.h"
>> +#include "intel_rc6.h"
>> +#include "selftest_engine_heartbeat.h"
>> +#include "intel_rps.h"
>> +#include "selftests/igt_flush_test.h"
>> +#include "selftests/igt_spinner.h"
> 
> wrong order ?

Removed all includes, since these are already included in 
selftest_rps.c. This gets included in intel_rps.c while compiling the 
slpc selftest.

> 
>> +
>> +#define NUM_STEPS 5
>> +#define H2G_DELAY 50000
>> +#define delay_for_h2g() usleep_range(H2G_DELAY, H2G_DELAY + 10000)
>> +
>> +static int set_min_freq(struct intel_guc_slpc *slpc, int freq)
>> +{
>> +	int ret;
> 
> add empty line

done.

> 
>> +	ret = intel_guc_slpc_set_min_freq(slpc, freq);
>> +	if (ret) {
>> +		pr_err("Could not set min frequency to [%d]\n", freq);
>> +		return ret;
>> +	} else {
>> +		/* Delay to ensure h2g completes */
>> +		delay_for_h2g();
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +static int set_max_freq(struct intel_guc_slpc *slpc, int freq)
>> +{
>> +	int ret;
> 
> add empty line

done.

> 
>> +	ret = intel_guc_slpc_set_max_freq(slpc, freq);
>> +	if (ret) {
>> +		pr_err("Could not set maximum frequency [%d]\n",
>> +			freq);
>> +		return ret;
>> +	} else {
>> +		/* Delay to ensure h2g completes */
>> +		delay_for_h2g();
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +int live_slpc_clamp_min(void *arg)
>> +{
>> +	struct drm_i915_private *i915 = arg;
>> +	struct intel_gt *gt = &i915->gt;
>> +	struct intel_guc_slpc *slpc;
>> +	struct intel_rps *rps;
>> +	struct intel_engine_cs *engine;
>> +	enum intel_engine_id id;
>> +	struct igt_spinner spin;
>> +	int err = 0;
> 
> usually "err" is last decl

ok.

> 
>> +	u32 slpc_min_freq, slpc_max_freq;
>> +
>> +
> 
> too many empty lines

removed.

> 
>> +	slpc = &gt->uc.guc.slpc;
>> +	rps = &gt->rps;
> 
> could be initialized in decl above

ok.

> 
>> +
>> +	if (!intel_uc_uses_guc_slpc(&gt->uc))
>> +		return 0;
>> +
>> +	if (igt_spinner_init(&spin, gt))
>> +		return -ENOMEM;
>> +
>> +	if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) {
>> +		pr_err("Could not get SLPC max freq");
>> +		return -EIO;
>> +	}
>> +
>> +	if (intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq)) {
>> +		pr_err("Could not get SLPC min freq");
>> +		return -EIO;
>> +	}
>> +
>> +	if (slpc_min_freq == slpc_max_freq) {
>> +		pr_err("Min/Max are fused to the same value");
>> +		return -EINVAL;
>> +	}
> 
> 3x missing \n

done.

> 
>> +
>> +	intel_gt_pm_wait_for_idle(gt);
>> +	intel_gt_pm_get(gt);
>> +	for_each_engine(engine, gt, id) {
>> +		struct i915_request *rq;
>> +		u32 step, min_freq, req_freq;
>> +		u32 act_freq, max_act_freq;
>> +
>> +		if (!intel_engine_can_store_dword(engine))
>> +			continue;
>> +
>> +		/* Go from min to max in 5 steps */
>> +		step = (slpc_max_freq - slpc_min_freq)/NUM_STEPS;
> 
> add spaces ") / NUM"

ok.

> 
>> +		max_act_freq = slpc_min_freq;
>> +		for (min_freq = slpc_min_freq; min_freq < slpc_max_freq; min_freq+=step)
> 
> add spaces " += "

ok.

> 
>> +		{
>> +			err = set_min_freq(slpc, min_freq);
>> +			if (err)
>> +				break;
>> +
>> +			st_engine_heartbeat_disable(engine);
>> +
>> +
> 
> keep only one empty line

ok.

> 
>> +			rq = igt_spinner_create_request(&spin,
>> +					engine->kernel_context,
>> +					MI_NOOP);
>> +			if (IS_ERR(rq)) {
>> +				err = PTR_ERR(rq);
>> +				st_engine_heartbeat_enable(engine);
>> +				break;
>> +			}
>> +
>> +			i915_request_add(rq);
>> +
>> +			if (!igt_wait_for_spinner(&spin, rq)) {
>> +				pr_err("%s: Spinner did not start\n",
>> +					engine->name);
>> +				igt_spinner_end(&spin);
>> +				st_engine_heartbeat_enable(engine);
>> +				intel_gt_set_wedged(engine->gt);
>> +				err = -EIO;
>> +				break;
>> +			}
>> +
>> +			/* Wait for GuC to detect business and raise
>> +			 * requested frequency if necessary */
>> +			delay_for_h2g();
>> +
>> +			req_freq = intel_rps_read_punit_req_frequency(rps);
>> +
>> +			/* GuC requests freq in multiples of 50/3 MHz */
>> +			if (req_freq < (min_freq - 50/3)) {
>> +				pr_err("SWReq is %d, should be at least %d", req_freq,
>> +					min_freq - 50/3);
>> +				igt_spinner_end(&spin);
>> +				st_engine_heartbeat_enable(engine);
>> +				err = -EINVAL;
>> +				break;
>> +			}
>> +
>> +			act_freq =  intel_rps_read_actual_frequency(rps);
>> +			if (act_freq > max_act_freq)
>> +				max_act_freq = act_freq;
>> +
>> +			igt_spinner_end(&spin);
>> +			st_engine_heartbeat_enable(engine);
>> +		}
>> +
>> +		pr_info("Max actual frequency for %s was %d",
>> +				engine->name, max_act_freq);
>> +
>> +		/* Actual frequency should rise above min */
>> +		if (max_act_freq == slpc_min_freq) {
>> +			pr_err("Actual freq did not rise above min");
>> +			err = -EINVAL;
>> +		}
> 
> 2x missing \n
> 
> and few more below

added.

> 
>> +
>> +		if (err)
>> +			break;
>> +	}
>> +
>> +	/* Restore min/max frequencies */
>> +	set_max_freq(slpc, slpc_max_freq);
>> +	set_min_freq(slpc, slpc_min_freq);
>> +
>> +	if (igt_flush_test(gt->i915))
>> +		err = -EIO;
>> +
>> +	intel_gt_pm_put(gt);
>> +	igt_spinner_fini(&spin);
>> +	intel_gt_pm_wait_for_idle(gt);
>> +
>> +	return err;
>> +}
>> +
>> +int live_slpc_clamp_max(void *arg)
>> +{
>> +	struct drm_i915_private *i915 = arg;
>> +	struct intel_gt *gt = &i915->gt;
>> +	struct intel_guc_slpc *slpc;
>> +	struct intel_rps *rps;
>> +	struct intel_engine_cs *engine;
>> +	enum intel_engine_id id;
>> +	struct igt_spinner spin;
>> +	int err = 0;
>> +	u32 slpc_min_freq, slpc_max_freq;
>> +
>> +	slpc = &gt->uc.guc.slpc;
>> +	rps = &gt->rps;
>> +
>> +	if (!intel_uc_uses_guc_slpc(&gt->uc))
>> +		return 0;
>> +
>> +	if (igt_spinner_init(&spin, gt))
>> +		return -ENOMEM;
>> +
>> +	if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) {
>> +		pr_err("Could not get SLPC max freq");
>> +		return -EIO;
>> +	}
>> +
>> +	if (intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq)) {
>> +		pr_err("Could not get SLPC min freq");
>> +		return -EIO;
>> +	}
>> +
>> +	if (slpc_min_freq == slpc_max_freq) {
>> +		pr_err("Min/Max are fused to the same value");
>> +		return -EINVAL;
>> +	}
>> +
>> +	intel_gt_pm_wait_for_idle(gt);
>> +	intel_gt_pm_get(gt);
>> +	for_each_engine(engine, gt, id) {
>> +		struct i915_request *rq;
>> +		u32 max_freq, req_freq;
>> +		u32 act_freq, max_act_freq;
>> +		u32 step;
>> +
>> +		if (!intel_engine_can_store_dword(engine))
>> +			continue;
>> +
>> +		/* Go from max to min in 5 steps */
>> +		step = (slpc_max_freq - slpc_min_freq)/NUM_STEPS;
>> +		max_act_freq = slpc_min_freq;
>> +		for (max_freq = slpc_max_freq; max_freq > slpc_min_freq; max_freq-=step)
>> +		{
>> +			err = set_max_freq(slpc, max_freq);
>> +			if (err)
>> +				break;
>> +
>> +			st_engine_heartbeat_disable(engine);
>> +
>> +			rq = igt_spinner_create_request(&spin,
>> +						engine->kernel_context,
>> +						MI_NOOP);
>> +			if (IS_ERR(rq)) {
>> +				st_engine_heartbeat_enable(engine);
>> +				err = PTR_ERR(rq);
>> +				break;
>> +			}
>> +
>> +			i915_request_add(rq);
>> +
>> +			if (!igt_wait_for_spinner(&spin, rq)) {
>> +				pr_err("%s: SLPC spinner did not start\n",
>> +				       engine->name);
>> +				igt_spinner_end(&spin);
>> +				st_engine_heartbeat_enable(engine);
>> +				intel_gt_set_wedged(engine->gt);
>> +				err = -EIO;
>> +				break;
>> +			}
>> +
>> +			delay_for_h2g();
>> +
>> +			/* Verify that SWREQ indeed was set to specific value */
>> +			req_freq = intel_rps_read_punit_req_frequency(rps);
>> +
>> +			/* GuC requests freq in multiples of 50/3 MHz */
>> +			if (req_freq > (max_freq + 50/3)) {
>> +				pr_err("SWReq is %d, should be at most %d", req_freq,
>> +					max_freq + 50/3);
>> +				igt_spinner_end(&spin);
>> +				st_engine_heartbeat_enable(engine);
>> +				err = -EINVAL;
>> +				break;
>> +			}
>> +
>> +			act_freq =  intel_rps_read_actual_frequency(rps);
>> +			if (act_freq > max_act_freq)
>> +				max_act_freq = act_freq;
>> +
>> +			st_engine_heartbeat_enable(engine);
>> +			igt_spinner_end(&spin);
>> +
>> +			if (err)
>> +				break;
>> +		}
>> +
>> +		pr_info("Max actual frequency for %s was %d",
>> +				engine->name, max_act_freq);
>> +
>> +		/* Actual frequency should rise above min */
>> +		if (max_act_freq == slpc_min_freq) {
>> +			pr_err("Actual freq did not rise above min");
>> +			err = -EINVAL;
>> +		}
>> +
>> +		if (igt_flush_test(gt->i915)) {
>> +			err = -EIO;
>> +			break;
>> +		}
>> +
>> +		if (err)
>> +			break;
>> +	}
>> +
>> +	/* Restore min/max freq */
>> +	set_max_freq(slpc, slpc_max_freq);
>> +	set_min_freq(slpc, slpc_min_freq);
>> +
>> +	intel_gt_pm_put(gt);
>> +	igt_spinner_fini(&spin);
>> +	intel_gt_pm_wait_for_idle(gt);
>> +
>> +	return err;
>> +}
>> +
>> +int intel_slpc_live_selftests(struct drm_i915_private *i915)
>> +{
>> +	static const struct i915_subtest tests[] = {
>> +		SUBTEST(live_slpc_clamp_max),
>> +		SUBTEST(live_slpc_clamp_min),
>> +	};
>> +
>> +	if (intel_gt_is_wedged(&i915->gt))
>> +		return 0;
>> +
>> +	return i915_live_subtests(tests, i915);
>> +}
>> diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.h b/drivers/gpu/drm/i915/gt/selftest_slpc.h
>> new file mode 100644
>> index 000000000000..8dfb40916a8c
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/gt/selftest_slpc.h
>> @@ -0,0 +1,12 @@
>> +/* SPDX-License-Identifier: MIT */
>> +/*
>> + * Copyright © 2020 Intel Corporation
> 
> 2021

done.
Thanks,
Vinay.
> 
> Michal
> 
>> + */
>> +
>> +#ifndef SELFTEST_SLPC_H
>> +#define SELFTEST_SLPC_H
>> +
>> +int live_slpc_clamp_max(void *arg);
>> +int live_slpc_clamp_min(void *arg);
>> +
>> +#endif /* SELFTEST_SLPC_H */
>> diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
>> index e2fd1b61af71..1746a56dda06 100644
>> --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
>> +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
>> @@ -47,5 +47,6 @@ selftest(hangcheck, intel_hangcheck_live_selftests)
>>   selftest(execlists, intel_execlists_live_selftests)
>>   selftest(ring_submission, intel_ring_submission_live_selftests)
>>   selftest(perf, i915_perf_live_selftests)
>> +selftest(slpc, intel_slpc_live_selftests)
>>   /* Here be dragons: keep last to run last! */
>>   selftest(late_gt_pm, intel_gt_pm_late_selftests)
>>

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Intel-gfx] [PATCH 16/16] drm/i915/guc/rc: Setup and enable GUCRC feature
  2021-07-10 18:41   ` [Intel-gfx] " Michal Wajdeczko
@ 2021-07-21  1:11     ` Belgaumkar, Vinay
  0 siblings, 0 replies; 49+ messages in thread
From: Belgaumkar, Vinay @ 2021-07-21  1:11 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx, dri-devel



On 7/10/2021 11:41 AM, Michal Wajdeczko wrote:
> 
> 
> On 10.07.2021 03:20, Vinay Belgaumkar wrote:
>> This feature hands over the control of HW RC6 to the GUC.
>> GUC decides when to put HW into RC6 based on it's internal
>> busyness algorithms.
>>
>> GUCRC needs GUC submission to be enabled, and only
>> supported on Gen12+ for now.
>>
>> When GUCRC is enabled, do not set HW RC6. Use a H2G message
>> to tell guc to enable GUCRC. When disabling RC6, tell guc to
> 
> s/GUC/GuC
> s/guc/GuC

Done.

> 
>> revert RC6 control back to KMD.
>>
>> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
>> ---
>>   drivers/gpu/drm/i915/Makefile                 |  1 +
>>   drivers/gpu/drm/i915/gt/intel_rc6.c           | 22 ++++--
>>   .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h  |  6 ++
>>   drivers/gpu/drm/i915/gt/uc/intel_guc.c        |  1 +
>>   drivers/gpu/drm/i915/gt/uc/intel_guc.h        |  2 +
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c     | 79 +++++++++++++++++++
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h     | 32 ++++++++
>>   drivers/gpu/drm/i915/gt/uc/intel_uc.h         |  2 +
>>   8 files changed, 140 insertions(+), 5 deletions(-)
>>   create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
>>   create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h
>>
>> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
>> index d8eac4468df9..3fc17f20d88e 100644
>> --- a/drivers/gpu/drm/i915/Makefile
>> +++ b/drivers/gpu/drm/i915/Makefile
>> @@ -186,6 +186,7 @@ i915-y += gt/uc/intel_uc.o \
>>   	  gt/uc/intel_guc_fw.o \
>>   	  gt/uc/intel_guc_log.o \
>>   	  gt/uc/intel_guc_log_debugfs.o \
>> +	  gt/uc/intel_guc_rc.o \
>>   	  gt/uc/intel_guc_slpc.o \
>>   	  gt/uc/intel_guc_submission.o \
>>   	  gt/uc/intel_huc.o \
>> diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c
>> index 259d7eb4e165..299fcf10b04b 100644
>> --- a/drivers/gpu/drm/i915/gt/intel_rc6.c
>> +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c
>> @@ -98,11 +98,19 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6)
>>   	set(uncore, GEN9_MEDIA_PG_IDLE_HYSTERESIS, 60);
>>   	set(uncore, GEN9_RENDER_PG_IDLE_HYSTERESIS, 60);
>>   
>> -	/* 3a: Enable RC6 */
>> -	rc6->ctl_enable =
>> -		GEN6_RC_CTL_HW_ENABLE |
>> -		GEN6_RC_CTL_RC6_ENABLE |
>> -		GEN6_RC_CTL_EI_MODE(1);
>> +	/* 3a: Enable RC6
>> +	 *
>> +	 * With GUCRC, we do not enable bit 31 of RC_CTL,
>> +	 * thus allowing GuC to control RC6 entry/exit fully instead.
>> +	 * We will not set the HW ENABLE and EI bits
>> +	 */
>> +	if (!intel_guc_rc_enable(&gt->uc.guc))
>> +		rc6->ctl_enable = GEN6_RC_CTL_RC6_ENABLE;
>> +	else
>> +		rc6->ctl_enable =
>> +			GEN6_RC_CTL_HW_ENABLE |
>> +			GEN6_RC_CTL_RC6_ENABLE |
>> +			GEN6_RC_CTL_EI_MODE(1);
>>   
>>   	pg_enable =
>>   		GEN9_RENDER_PG_ENABLE |
>> @@ -513,6 +521,10 @@ static void __intel_rc6_disable(struct intel_rc6 *rc6)
>>   {
>>   	struct drm_i915_private *i915 = rc6_to_i915(rc6);
>>   	struct intel_uncore *uncore = rc6_to_uncore(rc6);
>> +	struct intel_gt *gt = rc6_to_gt(rc6);
>> +
>> +	/* Take control of RC6 back from GuC */
>> +	intel_guc_rc_disable(&gt->uc.guc);
>>   
>>   	intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
>>   	if (GRAPHICS_VER(i915) >= 9)
>> diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
>> index 596cf4b818e5..2ddb9cdc0a59 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
>> @@ -136,6 +136,7 @@ enum intel_guc_action {
>>   	INTEL_GUC_ACTION_CONTEXT_RESET_NOTIFICATION = 0x1008,
>>   	INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION = 0x1009,
>>   	INTEL_GUC_ACTION_SLPC_REQUEST = 0x3003,
>> +	INTEL_GUC_ACTION_SETUP_PC_GUCRC = 0x3004,
>>   	INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000,
>>   	INTEL_GUC_ACTION_REGISTER_CONTEXT = 0x4502,
>>   	INTEL_GUC_ACTION_DEREGISTER_CONTEXT = 0x4503,
>> @@ -146,6 +147,11 @@ enum intel_guc_action {
>>   	INTEL_GUC_ACTION_LIMIT
>>   };
>>   
>> +enum intel_guc_rc_options {
>> +	INTEL_GUCRC_HOST_CONTROL,
>> +	INTEL_GUCRC_FIRMWARE_CONTROL,
>> +};
>> +
>>   enum intel_guc_preempt_options {
>>   	INTEL_GUC_PREEMPT_OPTION_DROP_WORK_Q = 0x4,
>>   	INTEL_GUC_PREEMPT_OPTION_DROP_SUBMIT_Q = 0x8,
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> index 82863a9bc8e8..0d55b24f7c67 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> @@ -158,6 +158,7 @@ void intel_guc_init_early(struct intel_guc *guc)
>>   	intel_guc_log_init_early(&guc->log);
>>   	intel_guc_submission_init_early(guc);
>>   	intel_guc_slpc_init_early(guc);
>> +	intel_guc_rc_init_early(guc);
>>   
>>   	mutex_init(&guc->send_mutex);
>>   	spin_lock_init(&guc->irq_lock);
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
>> index 0dbbd9cf553f..592d52e5e93c 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
>> @@ -59,6 +59,8 @@ struct intel_guc {
>>   
>>   	bool submission_supported;
>>   	bool submission_selected;
>> +	bool rc_supported;
>> +	bool rc_selected;
>>   	bool slpc_supported;
>>   	bool slpc_selected;
>>   
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
>> new file mode 100644
>> index 000000000000..45b61432c56d
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
>> @@ -0,0 +1,79 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright © 2020 Intel Corporation
> 
> 2021

Done.
> 
>> +*/
> 
> unaligned *

done.

> 
>> +
>> +#include "intel_guc_rc.h"
>> +#include "gt/intel_gt.h"
>> +#include "i915_drv.h"
>> +
>> +static bool __guc_rc_supported(struct intel_guc *guc)
>> +{
>> +	/* GuC RC is unavailable for pre-Gen12 */
>> +	return guc->submission_supported &&
>> +		GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12;
>> +}
>> +
>> +static bool __guc_rc_selected(struct intel_guc *guc)
>> +{
>> +	if (!intel_guc_rc_is_supported(guc))
>> +		return false;
>> +
>> +	return guc->submission_selected;
>> +}
>> +
>> +void intel_guc_rc_init_early(struct intel_guc *guc)
>> +{
>> +	guc->rc_supported = __guc_rc_supported(guc);
>> +	guc->rc_selected = __guc_rc_selected(guc);
>> +}
>> +
>> +static int guc_action_control_gucrc(struct intel_guc *guc, bool enable)
>> +{
>> +	struct drm_device *drm = &guc_to_gt(guc)->i915->drm;
>> +	u32 rc_mode = enable ? INTEL_GUCRC_FIRMWARE_CONTROL :
>> +				INTEL_GUCRC_HOST_CONTROL;
>> +	u32 action[] = {
>> +		INTEL_GUC_ACTION_SETUP_PC_GUCRC,
>> +		rc_mode
>> +	};
>> +	int ret;
>> +
>> +	ret = intel_guc_send(guc, action, ARRAY_SIZE(action));
>> +	if (ret)
> 
> since intel_guc_send() may return non-zero value from data0 RESPONSE
> field, assuming that this action expects there MBZ this should be:
> 
> 	ret = ret > 0 ? -EPROTO : ret;
> 
> otherwise some static code analyzers might complain
> 
>> +		drm_err(drm, "Failed to set GUCRC mode(%d), err=%d\n",
> 
> you may want to print error with %pe
> and move this message to __guc_rc_control because of the above

Ok, done.

> 
>> +			rc_mode, ret);
>> +
>> +	return ret;
>> +}
>> +
>> +static int __guc_rc_control(struct intel_guc *guc, bool enable)
>> +{
>> +	struct intel_gt *gt = guc_to_gt(guc);
>> +	int ret;
>> +
>> +	if (!intel_uc_uses_guc_rc(&gt->uc))
>> +		return -ENOTSUPP;
>> +
>> +	if (!intel_guc_is_ready(guc))
>> +		return -EINVAL;
>> +
>> +	ret = guc_action_control_gucrc(guc, enable);
>> +	if (unlikely(ret))
> 
> 	drm_err(drm, "Failed to %s GuC RC mode (%pe)\n",
> 		enabledisable(enable), ERR_PTR(ret));
> 
>> +		return ret;
>> +
>> +	drm_info(&gt->i915->drm, "GuC RC %s\n",
>> +	         enableddisabled(enable));
>> +
>> +	return 0;
>> +}
>> +
>> +int intel_guc_rc_enable(struct intel_guc *guc)
>> +{
>> +	return __guc_rc_control(guc, true);
>> +}
>> +
>> +int intel_guc_rc_disable(struct intel_guc *guc)
>> +{
>> +	return __guc_rc_control(guc, false);
>> +}
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h
>> new file mode 100644
>> index 000000000000..169e60726e5b
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h
>> @@ -0,0 +1,32 @@
>> +/* SPDX-License-Identifier: MIT */
>> +/*
>> + * Copyright © 2020 Intel Corporation
> 
> 2021

Done.

> 
>> + */
>> +
>> +#ifndef _INTEL_GUC_RC_H_
>> +#define _INTEL_GUC_RC_H_
>> +
>> +#include <linux/types.h>
> 
> do you need this include here ?

guess not.

Thanks,
Vinay.
> 
> Michal
> 
>> +#include "intel_guc_submission.h"
>> +
>> +void intel_guc_rc_init_early(struct intel_guc *guc);
>> +
>> +static inline bool intel_guc_rc_is_supported(struct intel_guc *guc)
>> +{
>> +	return guc->rc_supported;
>> +}
>> +
>> +static inline bool intel_guc_rc_is_wanted(struct intel_guc *guc)
>> +{
>> +	return guc->submission_selected && intel_guc_rc_is_supported(guc);
>> +}
>> +
>> +static inline bool intel_guc_rc_is_used(struct intel_guc *guc)
>> +{
>> +	return intel_guc_submission_is_used(guc) && intel_guc_rc_is_wanted(guc);
>> +}
>> +
>> +int intel_guc_rc_enable(struct intel_guc *guc);
>> +int intel_guc_rc_disable(struct intel_guc *guc);
>> +
>> +#endif
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.h b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
>> index 38e465fd8a0c..29d8ad6d9087 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
>> @@ -7,6 +7,7 @@
>>   #define _INTEL_UC_H_
>>   
>>   #include "intel_guc.h"
>> +#include "intel_guc_rc.h"
>>   #include "intel_guc_submission.h"
>>   #include "intel_huc.h"
>>   #include "i915_params.h"
>> @@ -84,6 +85,7 @@ uc_state_checkers(guc, guc);
>>   uc_state_checkers(huc, huc);
>>   uc_state_checkers(guc, guc_submission);
>>   uc_state_checkers(guc, guc_slpc);
>> +uc_state_checkers(guc, guc_rc);
>>   
>>   #undef uc_state_checkers
>>   #undef __uc_state_checker
>>

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Intel-gfx] [PATCH 07/16] drm/i915/guc/slpc: Enable slpc and add related H2G events
  2021-07-15  1:58     ` Belgaumkar, Vinay
@ 2021-07-21 17:36       ` Michal Wajdeczko
  0 siblings, 0 replies; 49+ messages in thread
From: Michal Wajdeczko @ 2021-07-21 17:36 UTC (permalink / raw)
  To: Belgaumkar, Vinay, intel-gfx, dri-devel



On 15.07.2021 03:58, Belgaumkar, Vinay wrote:
> 
> 
> On 7/10/2021 10:37 AM, Michal Wajdeczko wrote:
>>
>>
>> On 10.07.2021 03:20, Vinay Belgaumkar wrote:
...
>>>   diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
>>> b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
>>> index e2644a05f298..3e76d4d5f7bb 100644
>>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
>>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
>>> @@ -2321,10 +2321,6 @@ void intel_guc_submission_enable(struct
>>> intel_guc *guc)
>>>     void intel_guc_submission_disable(struct intel_guc *guc)
>>>   {
>>> -    struct intel_gt *gt = guc_to_gt(guc);
>>> -
>>> -    GEM_BUG_ON(gt->awake); /* GT should be parked first */
>>
>> if not mistake, can you explain why it was removed ?
> 
> This was part of a different commit. The BUG_ON in
> disable_guc_submission was added with an assumption that it will be
> called only during driver unload and not expected to hold any GT PM
> references. Since this needs to be called from an error scenario during
> slpc enable, remove the BUG_ON. Do we need this as a separate commit?

yes, please

Michal


^ permalink raw reply	[flat|nested] 49+ messages in thread

end of thread, other threads:[~2021-07-21 17:36 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-10  1:20 [PATCH 00/16] Enable GuC based power management features Vinay Belgaumkar
2021-07-10  1:20 ` [PATCH 02/16] drm/i915/guc/slpc: Initial definitions for slpc Vinay Belgaumkar
2021-07-10 14:27   ` Michal Wajdeczko
2021-07-12 18:40     ` Belgaumkar, Vinay
2021-07-12 23:43     ` Belgaumkar, Vinay
2021-07-10  1:20 ` [PATCH 03/16] drm/i915/guc/slpc: Gate Host RPS when slpc is enabled Vinay Belgaumkar
2021-07-10  1:20 ` [PATCH 04/16] drm/i915/guc/slpc: Lay out slpc init/enable/disable/fini Vinay Belgaumkar
2021-07-10 14:35   ` [Intel-gfx] " Michal Wajdeczko
2021-07-13  0:37     ` Belgaumkar, Vinay
2021-07-10  1:20 ` [PATCH 05/16] drm/i915/guc/slpc: Adding slpc communication interfaces Vinay Belgaumkar
2021-07-10 15:52   ` Michal Wajdeczko
2021-07-13 23:22     ` Belgaumkar, Vinay
2021-07-10  1:20 ` [PATCH 06/16] drm/i915/guc/slpc: Allocate, initialize and release slpc Vinay Belgaumkar
2021-07-10 16:05   ` Michal Wajdeczko
2021-07-14  1:40     ` Belgaumkar, Vinay
2021-07-10  1:20 ` [PATCH 07/16] drm/i915/guc/slpc: Enable slpc and add related H2G events Vinay Belgaumkar
2021-07-10 17:37   ` [Intel-gfx] " Michal Wajdeczko
2021-07-15  1:58     ` Belgaumkar, Vinay
2021-07-21 17:36       ` Michal Wajdeczko
2021-07-10  1:20 ` [PATCH 08/16] drm/i915/guc/slpc: Add methods to set min/max frequency Vinay Belgaumkar
2021-07-10  3:07   ` kernel test robot
2021-07-10  5:17   ` kernel test robot
2021-07-10 17:47   ` Michal Wajdeczko
2021-07-16 18:00     ` Belgaumkar, Vinay
2021-07-10  1:20 ` [PATCH 09/16] drm/i915/guc/slpc: Add get max/min freq hooks Vinay Belgaumkar
2021-07-10 17:52   ` Michal Wajdeczko
2021-07-20 22:08     ` Belgaumkar, Vinay
2021-07-10  1:20 ` [PATCH 10/16] drm/i915/guc/slpc: Add debugfs for slpc info Vinay Belgaumkar
2021-07-10 18:08   ` Michal Wajdeczko
2021-07-20 23:00     ` Belgaumkar, Vinay
2021-07-10  1:20 ` [PATCH 11/16] drm/i915/guc/slpc: Enable ARAT timer interrupt Vinay Belgaumkar
2021-07-10  1:20 ` [PATCH 12/16] drm/i915/guc/slpc: Cache platform frequency limits for slpc Vinay Belgaumkar
2021-07-10 18:15   ` [Intel-gfx] " Michal Wajdeczko
2021-07-17 19:30     ` Belgaumkar, Vinay
2021-07-20 23:05     ` Belgaumkar, Vinay
2021-07-10  1:20 ` [PATCH 13/16] drm/i915/guc/slpc: Update slpc to use platform min/max Vinay Belgaumkar
2021-07-10  1:20 ` [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc Vinay Belgaumkar
2021-07-10  6:18   ` kernel test robot
2021-07-10  7:30   ` kernel test robot
2021-07-10  7:30   ` [RFC PATCH] drm/i915/guc/slpc: intel_rps_read_punit_req() can be static kernel test robot
2021-07-10 13:54   ` [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc kernel test robot
2021-07-10 18:20   ` Michal Wajdeczko
2021-07-20 23:38     ` Belgaumkar, Vinay
2021-07-10  1:20 ` [PATCH 15/16] drm/i915/guc/slpc: slpc selftest Vinay Belgaumkar
2021-07-10 18:29   ` Michal Wajdeczko
2021-07-21  1:06     ` Belgaumkar, Vinay
2021-07-10  1:20 ` [PATCH 16/16] drm/i915/guc/rc: Setup and enable GUCRC feature Vinay Belgaumkar
2021-07-10 18:41   ` [Intel-gfx] " Michal Wajdeczko
2021-07-21  1:11     ` Belgaumkar, Vinay

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).