All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] Introduce multitile support
@ 2022-01-17 15:09 ` Andi Shyti
  0 siblings, 0 replies; 17+ messages in thread
From: Andi Shyti @ 2022-01-17 15:09 UTC (permalink / raw)
  To: Intel GFX, DRI Devel
  Cc: Abdiel Janulgue, Andi Shyti, Tvrtko Ursulin, Lucas De Marchi,
	Daniele Ceraolo Spurio, Matthew Auld, Andi Shyti,
	Sujaritha Sundaresan

Hi,

This is the second series that prepares i915 to host multitile
platforms. It introduces the for_each_gt() macro that loops over
the tiles to perform per gt actions.

This patch is a combination of two patches developed originally
by Abdiel, who introduced some refactoring during probe, and then
Tvrtko has added the necessary tools to start using the various
tiles.

The second patch re-organises the sysfs interface to expose the
API for each of the GTs. I decided to prioritise this patch
over others to unblock Sujaritha for further development.

A third series will still follow this.

Thanks,
Andi

Patchwork: https://patchwork.freedesktop.org/series/98741/

Changelog
=========
v2 -> v3
 - Added Matt and Sujaritha's r-b for patch 1 and 2.
 - Reworded the commit of patch 2 to underline the fact that the
   interface is useful also when used manually.
v1 -> v2
 - fixed a couple of coding style issues in patch 2.

Andi Shyti (1):
  drm/i915/gt: make a gt sysfs group and move power management files

Tvrtko Ursulin (1):
  drm/i915: Prepare for multiple GTs

 drivers/gpu/drm/i915/Makefile                 |   4 +-
 drivers/gpu/drm/i915/gt/intel_gt.c            | 141 ++++++-
 drivers/gpu/drm/i915/gt/intel_gt.h            |  14 +-
 drivers/gpu/drm/i915/gt/intel_gt_pm.c         |   9 +-
 drivers/gpu/drm/i915/gt/intel_gt_types.h      |   7 +
 drivers/gpu/drm/i915/gt/sysfs_gt.c            | 126 ++++++
 drivers/gpu/drm/i915/gt/sysfs_gt.h            |  44 ++
 drivers/gpu/drm/i915/gt/sysfs_gt_pm.c         | 393 ++++++++++++++++++
 drivers/gpu/drm/i915/gt/sysfs_gt_pm.h         |  16 +
 drivers/gpu/drm/i915/i915_driver.c            |  29 +-
 drivers/gpu/drm/i915/i915_drv.h               |   8 +
 drivers/gpu/drm/i915/i915_reg.h               |   1 +
 drivers/gpu/drm/i915/i915_sysfs.c             | 315 +-------------
 drivers/gpu/drm/i915/i915_sysfs.h             |   3 +
 drivers/gpu/drm/i915/intel_memory_region.h    |   3 +
 drivers/gpu/drm/i915/intel_uncore.c           |  12 +-
 drivers/gpu/drm/i915/intel_uncore.h           |   3 +-
 .../gpu/drm/i915/selftests/mock_gem_device.c  |   5 +-
 18 files changed, 785 insertions(+), 348 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt.c
 create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt.h
 create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
 create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt_pm.h

-- 
2.34.1


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

* [Intel-gfx] [PATCH v3 0/2] Introduce multitile support
@ 2022-01-17 15:09 ` Andi Shyti
  0 siblings, 0 replies; 17+ messages in thread
From: Andi Shyti @ 2022-01-17 15:09 UTC (permalink / raw)
  To: Intel GFX, DRI Devel; +Cc: Abdiel Janulgue, Lucas De Marchi, Matthew Auld

Hi,

This is the second series that prepares i915 to host multitile
platforms. It introduces the for_each_gt() macro that loops over
the tiles to perform per gt actions.

This patch is a combination of two patches developed originally
by Abdiel, who introduced some refactoring during probe, and then
Tvrtko has added the necessary tools to start using the various
tiles.

The second patch re-organises the sysfs interface to expose the
API for each of the GTs. I decided to prioritise this patch
over others to unblock Sujaritha for further development.

A third series will still follow this.

Thanks,
Andi

Patchwork: https://patchwork.freedesktop.org/series/98741/

Changelog
=========
v2 -> v3
 - Added Matt and Sujaritha's r-b for patch 1 and 2.
 - Reworded the commit of patch 2 to underline the fact that the
   interface is useful also when used manually.
v1 -> v2
 - fixed a couple of coding style issues in patch 2.

Andi Shyti (1):
  drm/i915/gt: make a gt sysfs group and move power management files

Tvrtko Ursulin (1):
  drm/i915: Prepare for multiple GTs

 drivers/gpu/drm/i915/Makefile                 |   4 +-
 drivers/gpu/drm/i915/gt/intel_gt.c            | 141 ++++++-
 drivers/gpu/drm/i915/gt/intel_gt.h            |  14 +-
 drivers/gpu/drm/i915/gt/intel_gt_pm.c         |   9 +-
 drivers/gpu/drm/i915/gt/intel_gt_types.h      |   7 +
 drivers/gpu/drm/i915/gt/sysfs_gt.c            | 126 ++++++
 drivers/gpu/drm/i915/gt/sysfs_gt.h            |  44 ++
 drivers/gpu/drm/i915/gt/sysfs_gt_pm.c         | 393 ++++++++++++++++++
 drivers/gpu/drm/i915/gt/sysfs_gt_pm.h         |  16 +
 drivers/gpu/drm/i915/i915_driver.c            |  29 +-
 drivers/gpu/drm/i915/i915_drv.h               |   8 +
 drivers/gpu/drm/i915/i915_reg.h               |   1 +
 drivers/gpu/drm/i915/i915_sysfs.c             | 315 +-------------
 drivers/gpu/drm/i915/i915_sysfs.h             |   3 +
 drivers/gpu/drm/i915/intel_memory_region.h    |   3 +
 drivers/gpu/drm/i915/intel_uncore.c           |  12 +-
 drivers/gpu/drm/i915/intel_uncore.h           |   3 +-
 .../gpu/drm/i915/selftests/mock_gem_device.c  |   5 +-
 18 files changed, 785 insertions(+), 348 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt.c
 create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt.h
 create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
 create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt_pm.h

-- 
2.34.1


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

* [PATCH v3 1/2] drm/i915: Prepare for multiple GTs
  2022-01-17 15:09 ` [Intel-gfx] " Andi Shyti
@ 2022-01-17 15:09   ` Andi Shyti
  -1 siblings, 0 replies; 17+ messages in thread
From: Andi Shyti @ 2022-01-17 15:09 UTC (permalink / raw)
  To: Intel GFX, DRI Devel
  Cc: Abdiel Janulgue, Andi Shyti, Tvrtko Ursulin, Lucas De Marchi,
	Daniele Ceraolo Spurio, Matthew Auld, Andi Shyti,
	Sujaritha Sundaresan

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

On a multi-tile platform, each tile has its own registers + GGTT
space, and BAR 0 is extended to cover all of them.

Up to four gts are supported in i915->gt[], with slot zero
shadowing the existing i915->gt0 to enable source compatibility
with legacy driver paths. A for_each_gt macro is added to iterate
over the GTs and will be used by upcoming patches that convert
various parts of the driver to be multi-gt aware.

Only the primary/root tile is initialized for now; the other
tiles will be detected and plugged in by future patches once the
necessary infrastructure is in place to handle them.

Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
---
 drivers/gpu/drm/i915/gt/intel_gt.c            | 139 ++++++++++++++++--
 drivers/gpu/drm/i915/gt/intel_gt.h            |  14 +-
 drivers/gpu/drm/i915/gt/intel_gt_pm.c         |   9 +-
 drivers/gpu/drm/i915/gt/intel_gt_types.h      |   7 +
 drivers/gpu/drm/i915/i915_driver.c            |  29 ++--
 drivers/gpu/drm/i915/i915_drv.h               |   6 +
 drivers/gpu/drm/i915/intel_memory_region.h    |   3 +
 drivers/gpu/drm/i915/intel_uncore.c           |  12 +-
 drivers/gpu/drm/i915/intel_uncore.h           |   3 +-
 .../gpu/drm/i915/selftests/mock_gem_device.c  |   5 +-
 10 files changed, 185 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
index 622cdfed8a8b..17927da9e23e 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -27,7 +27,8 @@
 #include "shmem_utils.h"
 #include "pxp/intel_pxp.h"
 
-void __intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915)
+static void
+__intel_gt_init_early(struct intel_gt *gt)
 {
 	spin_lock_init(&gt->irq_lock);
 
@@ -47,19 +48,27 @@ void __intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915)
 	intel_rps_init_early(&gt->rps);
 }
 
+/* Preliminary initialization of Tile 0 */
 void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915)
 {
 	gt->i915 = i915;
 	gt->uncore = &i915->uncore;
+
+	__intel_gt_init_early(gt);
 }
 
-int intel_gt_probe_lmem(struct intel_gt *gt)
+static int intel_gt_probe_lmem(struct intel_gt *gt)
 {
 	struct drm_i915_private *i915 = gt->i915;
+	unsigned int instance = gt->info.id;
 	struct intel_memory_region *mem;
 	int id;
 	int err;
 
+	id = INTEL_REGION_LMEM + instance;
+	if (drm_WARN_ON(&i915->drm, id >= INTEL_REGION_STOLEN_SMEM))
+		return -ENODEV;
+
 	mem = intel_gt_setup_lmem(gt);
 	if (mem == ERR_PTR(-ENODEV))
 		mem = intel_gt_setup_fake_lmem(gt);
@@ -74,9 +83,8 @@ int intel_gt_probe_lmem(struct intel_gt *gt)
 		return err;
 	}
 
-	id = INTEL_REGION_LMEM;
-
 	mem->id = id;
+	mem->instance = instance;
 
 	intel_memory_region_set_name(mem, "local%u", mem->instance);
 
@@ -791,16 +799,21 @@ void intel_gt_driver_release(struct intel_gt *gt)
 	intel_gt_fini_buffer_pool(gt);
 }
 
-void intel_gt_driver_late_release(struct intel_gt *gt)
+void intel_gt_driver_late_release(struct drm_i915_private *i915)
 {
+	struct intel_gt *gt;
+	unsigned int id;
+
 	/* We need to wait for inflight RCU frees to release their grip */
 	rcu_barrier();
 
-	intel_uc_driver_late_release(&gt->uc);
-	intel_gt_fini_requests(gt);
-	intel_gt_fini_reset(gt);
-	intel_gt_fini_timelines(gt);
-	intel_engines_free(gt);
+	for_each_gt(gt, i915, id) {
+		intel_uc_driver_late_release(&gt->uc);
+		intel_gt_fini_requests(gt);
+		intel_gt_fini_reset(gt);
+		intel_gt_fini_timelines(gt);
+		intel_engines_free(gt);
+	}
 }
 
 /**
@@ -909,6 +922,112 @@ u32 intel_gt_read_register_fw(struct intel_gt *gt, i915_reg_t reg)
 	return intel_uncore_read_fw(gt->uncore, reg);
 }
 
+static int
+intel_gt_tile_setup(struct intel_gt *gt, phys_addr_t phys_addr)
+{
+	struct drm_i915_private *i915 = gt->i915;
+	unsigned int id = gt->info.id;
+	int ret;
+
+	if (id) {
+		struct intel_uncore_mmio_debug *mmio_debug;
+		struct intel_uncore *uncore;
+
+		/* For multi-tile platforms BAR0 must have at least 16MB per tile */
+		if (GEM_WARN_ON(pci_resource_len(to_pci_dev(i915->drm.dev), 0) <
+				(id + 1) * SZ_16M))
+			return -EINVAL;
+
+		uncore = kzalloc(sizeof(*uncore), GFP_KERNEL);
+		if (!gt->uncore)
+			return -ENOMEM;
+
+		mmio_debug = kzalloc(sizeof(*mmio_debug), GFP_KERNEL);
+		if (!mmio_debug) {
+			kfree(uncore);
+			return -ENOMEM;
+		}
+
+		gt->uncore = uncore;
+		gt->uncore->debug = mmio_debug;
+
+		__intel_gt_init_early(gt);
+	}
+
+	intel_uncore_init_early(gt->uncore, gt);
+
+	ret = intel_uncore_setup_mmio(gt->uncore, phys_addr);
+	if (ret)
+		return ret;
+
+	gt->phys_addr = phys_addr;
+
+	return 0;
+}
+
+static void
+intel_gt_tile_cleanup(struct intel_gt *gt)
+{
+	intel_uncore_cleanup_mmio(gt->uncore);
+
+	if (gt->info.id) {
+		kfree(gt->uncore);
+		kfree(gt);
+	}
+}
+
+int intel_gt_probe_all(struct drm_i915_private *i915)
+{
+	struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
+	struct intel_gt *gt = &i915->gt0;
+	phys_addr_t phys_addr;
+	unsigned int mmio_bar;
+	int ret;
+
+	mmio_bar = GRAPHICS_VER(i915) == 2 ? 1 : 0;
+	phys_addr = pci_resource_start(pdev, mmio_bar);
+
+	/*
+	 * We always have at least one primary GT on any device
+	 * and it has been already initialized early during probe
+	 * in i915_driver_probe()
+	 */
+	ret = intel_gt_tile_setup(gt, phys_addr);
+	if (ret)
+		return ret;
+
+	i915->gt[0] = gt;
+
+	/* TODO: add more tiles */
+	return 0;
+}
+
+int intel_gt_tiles_init(struct drm_i915_private *i915)
+{
+	struct intel_gt *gt;
+	unsigned int id;
+	int ret;
+
+	for_each_gt(gt, i915, id) {
+		ret = intel_gt_probe_lmem(gt);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+void intel_gt_release_all(struct drm_i915_private *i915)
+{
+	struct intel_gt *gt;
+	unsigned int id;
+
+	for_each_gt(gt, i915, id) {
+		intel_gt_tile_cleanup(gt);
+		i915->gt[id] = NULL;
+	}
+}
+
 void intel_gt_info_print(const struct intel_gt_info *info,
 			 struct drm_printer *p)
 {
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h
index 94e1bac8c0cc..fcd10d88612a 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt.h
@@ -35,9 +35,7 @@ static inline struct intel_gt *huc_to_gt(struct intel_huc *huc)
 }
 
 void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915);
-void __intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915);
 int intel_gt_assign_ggtt(struct intel_gt *gt);
-int intel_gt_probe_lmem(struct intel_gt *gt);
 int intel_gt_init_mmio(struct intel_gt *gt);
 int __must_check intel_gt_init_hw(struct intel_gt *gt);
 int intel_gt_init(struct intel_gt *gt);
@@ -47,7 +45,7 @@ void intel_gt_driver_unregister(struct intel_gt *gt);
 void intel_gt_driver_remove(struct intel_gt *gt);
 void intel_gt_driver_release(struct intel_gt *gt);
 
-void intel_gt_driver_late_release(struct intel_gt *gt);
+void intel_gt_driver_late_release(struct drm_i915_private *i915);
 
 int intel_gt_wait_for_idle(struct intel_gt *gt, long timeout);
 
@@ -86,6 +84,16 @@ static inline bool intel_gt_needs_read_steering(struct intel_gt *gt,
 
 u32 intel_gt_read_register_fw(struct intel_gt *gt, i915_reg_t reg);
 
+int intel_gt_probe_all(struct drm_i915_private *i915);
+int intel_gt_tiles_init(struct drm_i915_private *i915);
+void intel_gt_release_all(struct drm_i915_private *i915);
+
+#define for_each_gt(gt__, i915__, id__) \
+	for ((id__) = 0; \
+	     (id__) < I915_MAX_GT; \
+	     (id__)++) \
+		for_each_if(((gt__) = (i915__)->gt[(id__)]))
+
 void intel_gt_info_print(const struct intel_gt_info *info,
 			 struct drm_printer *p);
 
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
index c0fa41e4c803..e66479d33bc3 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
@@ -128,7 +128,14 @@ static const struct intel_wakeref_ops wf_ops = {
 
 void intel_gt_pm_init_early(struct intel_gt *gt)
 {
-	intel_wakeref_init(&gt->wakeref, gt->uncore->rpm, &wf_ops);
+	/*
+	 * We access the runtime_pm structure via gt->i915 here rather than
+	 * gt->uncore as we do elsewhere in the file because gt->uncore is not
+	 * yet initialized for all tiles at this point in the driver startup.
+	 * runtime_pm is per-device rather than per-tile, so this is still the
+	 * correct structure.
+	 */
+	intel_wakeref_init(&gt->wakeref, &gt->i915->runtime_pm, &wf_ops);
 	seqcount_mutex_init(&gt->stats.lock, &gt->wakeref.mutex);
 }
 
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h b/drivers/gpu/drm/i915/gt/intel_gt_types.h
index 14216cc471b1..7311e485faae 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h
@@ -180,7 +180,14 @@ struct intel_gt {
 
 	const struct intel_mmio_range *steering_table[NUM_STEERING_TYPES];
 
+	/*
+	 * Base of per-tile GTTMMADR where we can derive the MMIO and the GGTT.
+	 */
+	phys_addr_t phys_addr;
+
 	struct intel_gt_info {
+		unsigned int id;
+
 		intel_engine_mask_t engine_mask;
 
 		u32 l3bank_mask;
diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c
index 8bef67cb6c33..aa00965cd36c 100644
--- a/drivers/gpu/drm/i915/i915_driver.c
+++ b/drivers/gpu/drm/i915/i915_driver.c
@@ -316,9 +316,8 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
 	intel_device_info_subplatform_init(dev_priv);
 	intel_step_init(dev_priv);
 
-	intel_gt_init_early(to_gt(dev_priv), dev_priv);
+	/* All tiles share a single mmio_debug */
 	intel_uncore_mmio_debug_init_early(&dev_priv->mmio_debug);
-	intel_uncore_init_early(&dev_priv->uncore, to_gt(dev_priv));
 
 	spin_lock_init(&dev_priv->irq_lock);
 	spin_lock_init(&dev_priv->gpu_error.lock);
@@ -349,7 +348,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
 
 	intel_wopcm_init_early(&dev_priv->wopcm);
 
-	__intel_gt_init_early(to_gt(dev_priv), dev_priv);
+	intel_gt_init_early(to_gt(dev_priv), dev_priv);
 
 	i915_gem_init_early(dev_priv);
 
@@ -370,7 +369,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
 
 err_gem:
 	i915_gem_cleanup_early(dev_priv);
-	intel_gt_driver_late_release(to_gt(dev_priv));
+	intel_gt_driver_late_release(dev_priv);
 	intel_region_ttm_device_fini(dev_priv);
 err_ttm:
 	vlv_suspend_cleanup(dev_priv);
@@ -389,7 +388,7 @@ static void i915_driver_late_release(struct drm_i915_private *dev_priv)
 	intel_irq_fini(dev_priv);
 	intel_power_domains_cleanup(dev_priv);
 	i915_gem_cleanup_early(dev_priv);
-	intel_gt_driver_late_release(to_gt(dev_priv));
+	intel_gt_driver_late_release(dev_priv);
 	intel_region_ttm_device_fini(dev_priv);
 	vlv_suspend_cleanup(dev_priv);
 	i915_workqueues_cleanup(dev_priv);
@@ -420,13 +419,9 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv)
 	if (ret < 0)
 		return ret;
 
-	ret = intel_uncore_setup_mmio(&dev_priv->uncore);
-	if (ret < 0)
-		goto err_bridge;
-
 	ret = intel_uncore_init_mmio(&dev_priv->uncore);
 	if (ret)
-		goto err_mmio;
+		return ret;
 
 	/* Try to make sure MCHBAR is enabled before poking at it */
 	intel_setup_mchbar(dev_priv);
@@ -444,9 +439,6 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv)
 err_uncore:
 	intel_teardown_mchbar(dev_priv);
 	intel_uncore_fini_mmio(&dev_priv->uncore);
-err_mmio:
-	intel_uncore_cleanup_mmio(&dev_priv->uncore);
-err_bridge:
 	pci_dev_put(dev_priv->bridge_dev);
 
 	return ret;
@@ -460,7 +452,6 @@ static void i915_driver_mmio_release(struct drm_i915_private *dev_priv)
 {
 	intel_teardown_mchbar(dev_priv);
 	intel_uncore_fini_mmio(&dev_priv->uncore);
-	intel_uncore_cleanup_mmio(&dev_priv->uncore);
 	pci_dev_put(dev_priv->bridge_dev);
 }
 
@@ -593,7 +584,7 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
 	if (ret)
 		goto err_ggtt;
 
-	ret = intel_gt_probe_lmem(to_gt(dev_priv));
+	ret = intel_gt_tiles_init(dev_priv);
 	if (ret)
 		goto err_mem_regions;
 
@@ -858,10 +849,14 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	intel_vgpu_detect(i915);
 
-	ret = i915_driver_mmio_probe(i915);
+	ret = intel_gt_probe_all(i915);
 	if (ret < 0)
 		goto out_runtime_pm_put;
 
+	ret = i915_driver_mmio_probe(i915);
+	if (ret < 0)
+		goto out_tiles_cleanup;
+
 	ret = i915_driver_hw_probe(i915);
 	if (ret < 0)
 		goto out_cleanup_mmio;
@@ -918,6 +913,8 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	i915_ggtt_driver_late_release(i915);
 out_cleanup_mmio:
 	i915_driver_mmio_release(i915);
+out_tiles_cleanup:
+	intel_gt_release_all(i915);
 out_runtime_pm_put:
 	enable_rpm_wakeref_asserts(&i915->runtime_pm);
 	i915_driver_late_release(i915);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 890f1f6fbc49..ec76011366fb 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -983,6 +983,12 @@ struct drm_i915_private {
 	/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */
 	struct intel_gt gt0;
 
+	/*
+	 * i915->gt[0] == &i915->gt0
+	 */
+#define I915_MAX_GT 4
+	struct intel_gt *gt[I915_MAX_GT];
+
 	struct {
 		struct i915_gem_contexts {
 			spinlock_t lock; /* locks list */
diff --git a/drivers/gpu/drm/i915/intel_memory_region.h b/drivers/gpu/drm/i915/intel_memory_region.h
index 5625c9c38993..6a6324a08e72 100644
--- a/drivers/gpu/drm/i915/intel_memory_region.h
+++ b/drivers/gpu/drm/i915/intel_memory_region.h
@@ -30,6 +30,9 @@ enum intel_memory_type {
 enum intel_region_id {
 	INTEL_REGION_SMEM = 0,
 	INTEL_REGION_LMEM,
+	INTEL_REGION_LMEM1,
+	INTEL_REGION_LMEM2,
+	INTEL_REGION_LMEM3,
 	INTEL_REGION_STOLEN_SMEM,
 	INTEL_REGION_STOLEN_LMEM,
 	INTEL_REGION_UNKNOWN, /* Should be last */
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 41d082213e81..016639c1275d 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -2020,14 +2020,11 @@ static int i915_pmic_bus_access_notifier(struct notifier_block *nb,
 	return NOTIFY_OK;
 }
 
-int intel_uncore_setup_mmio(struct intel_uncore *uncore)
+int intel_uncore_setup_mmio(struct intel_uncore *uncore, phys_addr_t phys_addr)
 {
 	struct drm_i915_private *i915 = uncore->i915;
-	struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
-	int mmio_bar;
 	int mmio_size;
 
-	mmio_bar = GRAPHICS_VER(i915) == 2 ? 1 : 0;
 	/*
 	 * Before gen4, the registers and the GTT are behind different BARs.
 	 * However, from gen4 onwards, the registers and the GTT are shared
@@ -2044,7 +2041,7 @@ int intel_uncore_setup_mmio(struct intel_uncore *uncore)
 	else
 		mmio_size = 2 * 1024 * 1024;
 
-	uncore->regs = pci_iomap(pdev, mmio_bar, mmio_size);
+	uncore->regs = ioremap(phys_addr, mmio_size);
 	if (uncore->regs == NULL) {
 		drm_err(&i915->drm, "failed to map registers\n");
 		return -EIO;
@@ -2055,9 +2052,8 @@ int intel_uncore_setup_mmio(struct intel_uncore *uncore)
 
 void intel_uncore_cleanup_mmio(struct intel_uncore *uncore)
 {
-	struct pci_dev *pdev = to_pci_dev(uncore->i915->drm.dev);
-
-	pci_iounmap(pdev, uncore->regs);
+	if (uncore->regs)
+		iounmap(uncore->regs);
 }
 
 void intel_uncore_init_early(struct intel_uncore *uncore,
diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h
index 210fe2a71612..2989032b580b 100644
--- a/drivers/gpu/drm/i915/intel_uncore.h
+++ b/drivers/gpu/drm/i915/intel_uncore.h
@@ -29,6 +29,7 @@
 #include <linux/notifier.h>
 #include <linux/hrtimer.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/types.h>
 
 #include "i915_reg.h"
 
@@ -219,7 +220,7 @@ void
 intel_uncore_mmio_debug_init_early(struct intel_uncore_mmio_debug *mmio_debug);
 void intel_uncore_init_early(struct intel_uncore *uncore,
 			     struct intel_gt *gt);
-int intel_uncore_setup_mmio(struct intel_uncore *uncore);
+int intel_uncore_setup_mmio(struct intel_uncore *uncore, phys_addr_t phys_addr);
 int intel_uncore_init_mmio(struct intel_uncore *uncore);
 void intel_uncore_prune_engine_fw_domains(struct intel_uncore *uncore,
 					  struct intel_gt *gt);
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
index 28a0f054009a..79520f217c90 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
@@ -73,7 +73,7 @@ static void mock_device_release(struct drm_device *dev)
 	destroy_workqueue(i915->wq);
 
 	intel_region_ttm_device_fini(i915);
-	intel_gt_driver_late_release(to_gt(i915));
+	intel_gt_driver_late_release(i915);
 	intel_memory_regions_driver_release(i915);
 
 	drm_mode_config_cleanup(&i915->drm);
@@ -179,7 +179,6 @@ struct drm_i915_private *mock_gem_device(void)
 
 	i915_gem_init__mm(i915);
 	intel_gt_init_early(to_gt(i915), i915);
-	__intel_gt_init_early(to_gt(i915), i915);
 	mock_uncore_init(&i915->uncore, i915);
 	atomic_inc(&to_gt(i915)->wakeref.count); /* disable; no hw support */
 	to_gt(i915)->awake = -ENODEV;
@@ -227,7 +226,7 @@ struct drm_i915_private *mock_gem_device(void)
 err_drv:
 	intel_region_ttm_device_fini(i915);
 err_ttm:
-	intel_gt_driver_late_release(to_gt(i915));
+	intel_gt_driver_late_release(i915);
 	intel_memory_regions_driver_release(i915);
 	drm_mode_config_cleanup(&i915->drm);
 	mock_destroy_device(i915);
-- 
2.34.1


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

* [Intel-gfx] [PATCH v3 1/2] drm/i915: Prepare for multiple GTs
@ 2022-01-17 15:09   ` Andi Shyti
  0 siblings, 0 replies; 17+ messages in thread
From: Andi Shyti @ 2022-01-17 15:09 UTC (permalink / raw)
  To: Intel GFX, DRI Devel; +Cc: Abdiel Janulgue, Lucas De Marchi, Matthew Auld

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

On a multi-tile platform, each tile has its own registers + GGTT
space, and BAR 0 is extended to cover all of them.

Up to four gts are supported in i915->gt[], with slot zero
shadowing the existing i915->gt0 to enable source compatibility
with legacy driver paths. A for_each_gt macro is added to iterate
over the GTs and will be used by upcoming patches that convert
various parts of the driver to be multi-gt aware.

Only the primary/root tile is initialized for now; the other
tiles will be detected and plugged in by future patches once the
necessary infrastructure is in place to handle them.

Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
---
 drivers/gpu/drm/i915/gt/intel_gt.c            | 139 ++++++++++++++++--
 drivers/gpu/drm/i915/gt/intel_gt.h            |  14 +-
 drivers/gpu/drm/i915/gt/intel_gt_pm.c         |   9 +-
 drivers/gpu/drm/i915/gt/intel_gt_types.h      |   7 +
 drivers/gpu/drm/i915/i915_driver.c            |  29 ++--
 drivers/gpu/drm/i915/i915_drv.h               |   6 +
 drivers/gpu/drm/i915/intel_memory_region.h    |   3 +
 drivers/gpu/drm/i915/intel_uncore.c           |  12 +-
 drivers/gpu/drm/i915/intel_uncore.h           |   3 +-
 .../gpu/drm/i915/selftests/mock_gem_device.c  |   5 +-
 10 files changed, 185 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
index 622cdfed8a8b..17927da9e23e 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -27,7 +27,8 @@
 #include "shmem_utils.h"
 #include "pxp/intel_pxp.h"
 
-void __intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915)
+static void
+__intel_gt_init_early(struct intel_gt *gt)
 {
 	spin_lock_init(&gt->irq_lock);
 
@@ -47,19 +48,27 @@ void __intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915)
 	intel_rps_init_early(&gt->rps);
 }
 
+/* Preliminary initialization of Tile 0 */
 void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915)
 {
 	gt->i915 = i915;
 	gt->uncore = &i915->uncore;
+
+	__intel_gt_init_early(gt);
 }
 
-int intel_gt_probe_lmem(struct intel_gt *gt)
+static int intel_gt_probe_lmem(struct intel_gt *gt)
 {
 	struct drm_i915_private *i915 = gt->i915;
+	unsigned int instance = gt->info.id;
 	struct intel_memory_region *mem;
 	int id;
 	int err;
 
+	id = INTEL_REGION_LMEM + instance;
+	if (drm_WARN_ON(&i915->drm, id >= INTEL_REGION_STOLEN_SMEM))
+		return -ENODEV;
+
 	mem = intel_gt_setup_lmem(gt);
 	if (mem == ERR_PTR(-ENODEV))
 		mem = intel_gt_setup_fake_lmem(gt);
@@ -74,9 +83,8 @@ int intel_gt_probe_lmem(struct intel_gt *gt)
 		return err;
 	}
 
-	id = INTEL_REGION_LMEM;
-
 	mem->id = id;
+	mem->instance = instance;
 
 	intel_memory_region_set_name(mem, "local%u", mem->instance);
 
@@ -791,16 +799,21 @@ void intel_gt_driver_release(struct intel_gt *gt)
 	intel_gt_fini_buffer_pool(gt);
 }
 
-void intel_gt_driver_late_release(struct intel_gt *gt)
+void intel_gt_driver_late_release(struct drm_i915_private *i915)
 {
+	struct intel_gt *gt;
+	unsigned int id;
+
 	/* We need to wait for inflight RCU frees to release their grip */
 	rcu_barrier();
 
-	intel_uc_driver_late_release(&gt->uc);
-	intel_gt_fini_requests(gt);
-	intel_gt_fini_reset(gt);
-	intel_gt_fini_timelines(gt);
-	intel_engines_free(gt);
+	for_each_gt(gt, i915, id) {
+		intel_uc_driver_late_release(&gt->uc);
+		intel_gt_fini_requests(gt);
+		intel_gt_fini_reset(gt);
+		intel_gt_fini_timelines(gt);
+		intel_engines_free(gt);
+	}
 }
 
 /**
@@ -909,6 +922,112 @@ u32 intel_gt_read_register_fw(struct intel_gt *gt, i915_reg_t reg)
 	return intel_uncore_read_fw(gt->uncore, reg);
 }
 
+static int
+intel_gt_tile_setup(struct intel_gt *gt, phys_addr_t phys_addr)
+{
+	struct drm_i915_private *i915 = gt->i915;
+	unsigned int id = gt->info.id;
+	int ret;
+
+	if (id) {
+		struct intel_uncore_mmio_debug *mmio_debug;
+		struct intel_uncore *uncore;
+
+		/* For multi-tile platforms BAR0 must have at least 16MB per tile */
+		if (GEM_WARN_ON(pci_resource_len(to_pci_dev(i915->drm.dev), 0) <
+				(id + 1) * SZ_16M))
+			return -EINVAL;
+
+		uncore = kzalloc(sizeof(*uncore), GFP_KERNEL);
+		if (!gt->uncore)
+			return -ENOMEM;
+
+		mmio_debug = kzalloc(sizeof(*mmio_debug), GFP_KERNEL);
+		if (!mmio_debug) {
+			kfree(uncore);
+			return -ENOMEM;
+		}
+
+		gt->uncore = uncore;
+		gt->uncore->debug = mmio_debug;
+
+		__intel_gt_init_early(gt);
+	}
+
+	intel_uncore_init_early(gt->uncore, gt);
+
+	ret = intel_uncore_setup_mmio(gt->uncore, phys_addr);
+	if (ret)
+		return ret;
+
+	gt->phys_addr = phys_addr;
+
+	return 0;
+}
+
+static void
+intel_gt_tile_cleanup(struct intel_gt *gt)
+{
+	intel_uncore_cleanup_mmio(gt->uncore);
+
+	if (gt->info.id) {
+		kfree(gt->uncore);
+		kfree(gt);
+	}
+}
+
+int intel_gt_probe_all(struct drm_i915_private *i915)
+{
+	struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
+	struct intel_gt *gt = &i915->gt0;
+	phys_addr_t phys_addr;
+	unsigned int mmio_bar;
+	int ret;
+
+	mmio_bar = GRAPHICS_VER(i915) == 2 ? 1 : 0;
+	phys_addr = pci_resource_start(pdev, mmio_bar);
+
+	/*
+	 * We always have at least one primary GT on any device
+	 * and it has been already initialized early during probe
+	 * in i915_driver_probe()
+	 */
+	ret = intel_gt_tile_setup(gt, phys_addr);
+	if (ret)
+		return ret;
+
+	i915->gt[0] = gt;
+
+	/* TODO: add more tiles */
+	return 0;
+}
+
+int intel_gt_tiles_init(struct drm_i915_private *i915)
+{
+	struct intel_gt *gt;
+	unsigned int id;
+	int ret;
+
+	for_each_gt(gt, i915, id) {
+		ret = intel_gt_probe_lmem(gt);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+void intel_gt_release_all(struct drm_i915_private *i915)
+{
+	struct intel_gt *gt;
+	unsigned int id;
+
+	for_each_gt(gt, i915, id) {
+		intel_gt_tile_cleanup(gt);
+		i915->gt[id] = NULL;
+	}
+}
+
 void intel_gt_info_print(const struct intel_gt_info *info,
 			 struct drm_printer *p)
 {
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h
index 94e1bac8c0cc..fcd10d88612a 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt.h
@@ -35,9 +35,7 @@ static inline struct intel_gt *huc_to_gt(struct intel_huc *huc)
 }
 
 void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915);
-void __intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915);
 int intel_gt_assign_ggtt(struct intel_gt *gt);
-int intel_gt_probe_lmem(struct intel_gt *gt);
 int intel_gt_init_mmio(struct intel_gt *gt);
 int __must_check intel_gt_init_hw(struct intel_gt *gt);
 int intel_gt_init(struct intel_gt *gt);
@@ -47,7 +45,7 @@ void intel_gt_driver_unregister(struct intel_gt *gt);
 void intel_gt_driver_remove(struct intel_gt *gt);
 void intel_gt_driver_release(struct intel_gt *gt);
 
-void intel_gt_driver_late_release(struct intel_gt *gt);
+void intel_gt_driver_late_release(struct drm_i915_private *i915);
 
 int intel_gt_wait_for_idle(struct intel_gt *gt, long timeout);
 
@@ -86,6 +84,16 @@ static inline bool intel_gt_needs_read_steering(struct intel_gt *gt,
 
 u32 intel_gt_read_register_fw(struct intel_gt *gt, i915_reg_t reg);
 
+int intel_gt_probe_all(struct drm_i915_private *i915);
+int intel_gt_tiles_init(struct drm_i915_private *i915);
+void intel_gt_release_all(struct drm_i915_private *i915);
+
+#define for_each_gt(gt__, i915__, id__) \
+	for ((id__) = 0; \
+	     (id__) < I915_MAX_GT; \
+	     (id__)++) \
+		for_each_if(((gt__) = (i915__)->gt[(id__)]))
+
 void intel_gt_info_print(const struct intel_gt_info *info,
 			 struct drm_printer *p);
 
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
index c0fa41e4c803..e66479d33bc3 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
@@ -128,7 +128,14 @@ static const struct intel_wakeref_ops wf_ops = {
 
 void intel_gt_pm_init_early(struct intel_gt *gt)
 {
-	intel_wakeref_init(&gt->wakeref, gt->uncore->rpm, &wf_ops);
+	/*
+	 * We access the runtime_pm structure via gt->i915 here rather than
+	 * gt->uncore as we do elsewhere in the file because gt->uncore is not
+	 * yet initialized for all tiles at this point in the driver startup.
+	 * runtime_pm is per-device rather than per-tile, so this is still the
+	 * correct structure.
+	 */
+	intel_wakeref_init(&gt->wakeref, &gt->i915->runtime_pm, &wf_ops);
 	seqcount_mutex_init(&gt->stats.lock, &gt->wakeref.mutex);
 }
 
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h b/drivers/gpu/drm/i915/gt/intel_gt_types.h
index 14216cc471b1..7311e485faae 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h
@@ -180,7 +180,14 @@ struct intel_gt {
 
 	const struct intel_mmio_range *steering_table[NUM_STEERING_TYPES];
 
+	/*
+	 * Base of per-tile GTTMMADR where we can derive the MMIO and the GGTT.
+	 */
+	phys_addr_t phys_addr;
+
 	struct intel_gt_info {
+		unsigned int id;
+
 		intel_engine_mask_t engine_mask;
 
 		u32 l3bank_mask;
diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c
index 8bef67cb6c33..aa00965cd36c 100644
--- a/drivers/gpu/drm/i915/i915_driver.c
+++ b/drivers/gpu/drm/i915/i915_driver.c
@@ -316,9 +316,8 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
 	intel_device_info_subplatform_init(dev_priv);
 	intel_step_init(dev_priv);
 
-	intel_gt_init_early(to_gt(dev_priv), dev_priv);
+	/* All tiles share a single mmio_debug */
 	intel_uncore_mmio_debug_init_early(&dev_priv->mmio_debug);
-	intel_uncore_init_early(&dev_priv->uncore, to_gt(dev_priv));
 
 	spin_lock_init(&dev_priv->irq_lock);
 	spin_lock_init(&dev_priv->gpu_error.lock);
@@ -349,7 +348,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
 
 	intel_wopcm_init_early(&dev_priv->wopcm);
 
-	__intel_gt_init_early(to_gt(dev_priv), dev_priv);
+	intel_gt_init_early(to_gt(dev_priv), dev_priv);
 
 	i915_gem_init_early(dev_priv);
 
@@ -370,7 +369,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
 
 err_gem:
 	i915_gem_cleanup_early(dev_priv);
-	intel_gt_driver_late_release(to_gt(dev_priv));
+	intel_gt_driver_late_release(dev_priv);
 	intel_region_ttm_device_fini(dev_priv);
 err_ttm:
 	vlv_suspend_cleanup(dev_priv);
@@ -389,7 +388,7 @@ static void i915_driver_late_release(struct drm_i915_private *dev_priv)
 	intel_irq_fini(dev_priv);
 	intel_power_domains_cleanup(dev_priv);
 	i915_gem_cleanup_early(dev_priv);
-	intel_gt_driver_late_release(to_gt(dev_priv));
+	intel_gt_driver_late_release(dev_priv);
 	intel_region_ttm_device_fini(dev_priv);
 	vlv_suspend_cleanup(dev_priv);
 	i915_workqueues_cleanup(dev_priv);
@@ -420,13 +419,9 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv)
 	if (ret < 0)
 		return ret;
 
-	ret = intel_uncore_setup_mmio(&dev_priv->uncore);
-	if (ret < 0)
-		goto err_bridge;
-
 	ret = intel_uncore_init_mmio(&dev_priv->uncore);
 	if (ret)
-		goto err_mmio;
+		return ret;
 
 	/* Try to make sure MCHBAR is enabled before poking at it */
 	intel_setup_mchbar(dev_priv);
@@ -444,9 +439,6 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv)
 err_uncore:
 	intel_teardown_mchbar(dev_priv);
 	intel_uncore_fini_mmio(&dev_priv->uncore);
-err_mmio:
-	intel_uncore_cleanup_mmio(&dev_priv->uncore);
-err_bridge:
 	pci_dev_put(dev_priv->bridge_dev);
 
 	return ret;
@@ -460,7 +452,6 @@ static void i915_driver_mmio_release(struct drm_i915_private *dev_priv)
 {
 	intel_teardown_mchbar(dev_priv);
 	intel_uncore_fini_mmio(&dev_priv->uncore);
-	intel_uncore_cleanup_mmio(&dev_priv->uncore);
 	pci_dev_put(dev_priv->bridge_dev);
 }
 
@@ -593,7 +584,7 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
 	if (ret)
 		goto err_ggtt;
 
-	ret = intel_gt_probe_lmem(to_gt(dev_priv));
+	ret = intel_gt_tiles_init(dev_priv);
 	if (ret)
 		goto err_mem_regions;
 
@@ -858,10 +849,14 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	intel_vgpu_detect(i915);
 
-	ret = i915_driver_mmio_probe(i915);
+	ret = intel_gt_probe_all(i915);
 	if (ret < 0)
 		goto out_runtime_pm_put;
 
+	ret = i915_driver_mmio_probe(i915);
+	if (ret < 0)
+		goto out_tiles_cleanup;
+
 	ret = i915_driver_hw_probe(i915);
 	if (ret < 0)
 		goto out_cleanup_mmio;
@@ -918,6 +913,8 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	i915_ggtt_driver_late_release(i915);
 out_cleanup_mmio:
 	i915_driver_mmio_release(i915);
+out_tiles_cleanup:
+	intel_gt_release_all(i915);
 out_runtime_pm_put:
 	enable_rpm_wakeref_asserts(&i915->runtime_pm);
 	i915_driver_late_release(i915);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 890f1f6fbc49..ec76011366fb 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -983,6 +983,12 @@ struct drm_i915_private {
 	/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */
 	struct intel_gt gt0;
 
+	/*
+	 * i915->gt[0] == &i915->gt0
+	 */
+#define I915_MAX_GT 4
+	struct intel_gt *gt[I915_MAX_GT];
+
 	struct {
 		struct i915_gem_contexts {
 			spinlock_t lock; /* locks list */
diff --git a/drivers/gpu/drm/i915/intel_memory_region.h b/drivers/gpu/drm/i915/intel_memory_region.h
index 5625c9c38993..6a6324a08e72 100644
--- a/drivers/gpu/drm/i915/intel_memory_region.h
+++ b/drivers/gpu/drm/i915/intel_memory_region.h
@@ -30,6 +30,9 @@ enum intel_memory_type {
 enum intel_region_id {
 	INTEL_REGION_SMEM = 0,
 	INTEL_REGION_LMEM,
+	INTEL_REGION_LMEM1,
+	INTEL_REGION_LMEM2,
+	INTEL_REGION_LMEM3,
 	INTEL_REGION_STOLEN_SMEM,
 	INTEL_REGION_STOLEN_LMEM,
 	INTEL_REGION_UNKNOWN, /* Should be last */
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 41d082213e81..016639c1275d 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -2020,14 +2020,11 @@ static int i915_pmic_bus_access_notifier(struct notifier_block *nb,
 	return NOTIFY_OK;
 }
 
-int intel_uncore_setup_mmio(struct intel_uncore *uncore)
+int intel_uncore_setup_mmio(struct intel_uncore *uncore, phys_addr_t phys_addr)
 {
 	struct drm_i915_private *i915 = uncore->i915;
-	struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
-	int mmio_bar;
 	int mmio_size;
 
-	mmio_bar = GRAPHICS_VER(i915) == 2 ? 1 : 0;
 	/*
 	 * Before gen4, the registers and the GTT are behind different BARs.
 	 * However, from gen4 onwards, the registers and the GTT are shared
@@ -2044,7 +2041,7 @@ int intel_uncore_setup_mmio(struct intel_uncore *uncore)
 	else
 		mmio_size = 2 * 1024 * 1024;
 
-	uncore->regs = pci_iomap(pdev, mmio_bar, mmio_size);
+	uncore->regs = ioremap(phys_addr, mmio_size);
 	if (uncore->regs == NULL) {
 		drm_err(&i915->drm, "failed to map registers\n");
 		return -EIO;
@@ -2055,9 +2052,8 @@ int intel_uncore_setup_mmio(struct intel_uncore *uncore)
 
 void intel_uncore_cleanup_mmio(struct intel_uncore *uncore)
 {
-	struct pci_dev *pdev = to_pci_dev(uncore->i915->drm.dev);
-
-	pci_iounmap(pdev, uncore->regs);
+	if (uncore->regs)
+		iounmap(uncore->regs);
 }
 
 void intel_uncore_init_early(struct intel_uncore *uncore,
diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h
index 210fe2a71612..2989032b580b 100644
--- a/drivers/gpu/drm/i915/intel_uncore.h
+++ b/drivers/gpu/drm/i915/intel_uncore.h
@@ -29,6 +29,7 @@
 #include <linux/notifier.h>
 #include <linux/hrtimer.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/types.h>
 
 #include "i915_reg.h"
 
@@ -219,7 +220,7 @@ void
 intel_uncore_mmio_debug_init_early(struct intel_uncore_mmio_debug *mmio_debug);
 void intel_uncore_init_early(struct intel_uncore *uncore,
 			     struct intel_gt *gt);
-int intel_uncore_setup_mmio(struct intel_uncore *uncore);
+int intel_uncore_setup_mmio(struct intel_uncore *uncore, phys_addr_t phys_addr);
 int intel_uncore_init_mmio(struct intel_uncore *uncore);
 void intel_uncore_prune_engine_fw_domains(struct intel_uncore *uncore,
 					  struct intel_gt *gt);
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
index 28a0f054009a..79520f217c90 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
@@ -73,7 +73,7 @@ static void mock_device_release(struct drm_device *dev)
 	destroy_workqueue(i915->wq);
 
 	intel_region_ttm_device_fini(i915);
-	intel_gt_driver_late_release(to_gt(i915));
+	intel_gt_driver_late_release(i915);
 	intel_memory_regions_driver_release(i915);
 
 	drm_mode_config_cleanup(&i915->drm);
@@ -179,7 +179,6 @@ struct drm_i915_private *mock_gem_device(void)
 
 	i915_gem_init__mm(i915);
 	intel_gt_init_early(to_gt(i915), i915);
-	__intel_gt_init_early(to_gt(i915), i915);
 	mock_uncore_init(&i915->uncore, i915);
 	atomic_inc(&to_gt(i915)->wakeref.count); /* disable; no hw support */
 	to_gt(i915)->awake = -ENODEV;
@@ -227,7 +226,7 @@ struct drm_i915_private *mock_gem_device(void)
 err_drv:
 	intel_region_ttm_device_fini(i915);
 err_ttm:
-	intel_gt_driver_late_release(to_gt(i915));
+	intel_gt_driver_late_release(i915);
 	intel_memory_regions_driver_release(i915);
 	drm_mode_config_cleanup(&i915->drm);
 	mock_destroy_device(i915);
-- 
2.34.1


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

* [PATCH v3 2/2] drm/i915/gt: make a gt sysfs group and move power management files
  2022-01-17 15:09 ` [Intel-gfx] " Andi Shyti
@ 2022-01-17 15:09   ` Andi Shyti
  -1 siblings, 0 replies; 17+ messages in thread
From: Andi Shyti @ 2022-01-17 15:09 UTC (permalink / raw)
  To: Intel GFX, DRI Devel
  Cc: Abdiel Janulgue, Andi Shyti, Tvrtko Ursulin, Lucas De Marchi,
	Daniele Ceraolo Spurio, Matthew Auld, Andi Shyti,
	Sujaritha Sundaresan

The GT has its own properties and in sysfs they should be grouped
in the 'gt/' directory.

Create a 'gt/' directory in sysfs which will contain gt0...gtN
directories related to each tile configured in the GPU. Move the
power management files inside those directories.

The previous power management files are kept in their original
root directory to avoid breaking the ABI. They point to the tile
'0' and a warning message is printed whenever accessed to. The
deprecated interface needs for the CONFIG_SYSFS_DEPRECATED_V2
flag in order to be generated.

The new sysfs structure will have a similar layout for the 4 tile
case:

/sys/.../card0
         ├── gt
         │   ├── gt0
         │   │   ├── id
         │   │   ├── rc6_enable
         │   │   ├── rc6_residency_ms
         │   │   ├── rps_act_freq_mhz
         │   │   ├── rps_boost_freq_mhz
         │   │   ├── rps_cur_freq_mhz
         │   │   ├── rps_max_freq_mhz
         │   │   ├── rps_min_freq_mhz
         │   │   ├── rps_RP0_freq_mhz
         │   │   ├── rps_RP1_freq_mhz
         │   │   └── rps_RPn_freq_mhz
	 .   .
	 .   .
	 .   .
         │   └── gt3
         │       ├── id
         │       ├── rc6_enable
         │       ├── rc6_residency_ms
         │       ├── rps_act_freq_mhz
         │       ├── rps_boost_freq_mhz
         │       ├── rps_cur_freq_mhz
         │       ├── rps_max_freq_mhz
         │       ├── rps_min_freq_mhz
         │       ├── rps_RP0_freq_mhz
         │       ├── rps_RP1_freq_mhz
         │       └── rps_RPn_freq_mhz
         ├── gt_act_freq_mhz   -+
         ├── gt_boost_freq_mhz  |
         ├── gt_cur_freq_mhz    |    Original interface
         ├── gt_max_freq_mhz    +─-> kept as existing ABI;
         ├── gt_min_freq_mhz    |    it points to gt0/
         ├── gt_RP0_freq_mhz    |
         └── gt_RP1_freq_mhz    |
         └── gt_RPn_freq_mhz   -+

As soon as multitile platforms will start being supported, this
interface will allow to control the power (either manually or
with tools) on each tile, instead of affecting only tile 0 and
getting incomplete results.

Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
Cc: Matt Roper <matthew.d.roper@intel.com>
Cc: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
---
 drivers/gpu/drm/i915/Makefile         |   4 +-
 drivers/gpu/drm/i915/gt/intel_gt.c    |   2 +
 drivers/gpu/drm/i915/gt/sysfs_gt.c    | 126 +++++++++
 drivers/gpu/drm/i915/gt/sysfs_gt.h    |  44 +++
 drivers/gpu/drm/i915/gt/sysfs_gt_pm.c | 393 ++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gt/sysfs_gt_pm.h |  16 ++
 drivers/gpu/drm/i915/i915_drv.h       |   2 +
 drivers/gpu/drm/i915/i915_reg.h       |   1 +
 drivers/gpu/drm/i915/i915_sysfs.c     | 315 +--------------------
 drivers/gpu/drm/i915/i915_sysfs.h     |   3 +
 10 files changed, 600 insertions(+), 306 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt.c
 create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt.h
 create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
 create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt_pm.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index aa86ac33effc..5fd203c626fc 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -121,7 +121,9 @@ gt-y += \
 	gt/intel_timeline.o \
 	gt/intel_workarounds.o \
 	gt/shmem_utils.o \
-	gt/sysfs_engines.o
+	gt/sysfs_engines.o \
+	gt/sysfs_gt.o \
+	gt/sysfs_gt_pm.o
 # autogenerated null render state
 gt-y += \
 	gt/gen6_renderstate.o \
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
index 17927da9e23e..2584c51c1c14 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -25,6 +25,7 @@
 #include "intel_rps.h"
 #include "intel_uncore.h"
 #include "shmem_utils.h"
+#include "sysfs_gt.h"
 #include "pxp/intel_pxp.h"
 
 static void
@@ -453,6 +454,7 @@ void intel_gt_driver_register(struct intel_gt *gt)
 	intel_rps_driver_register(&gt->rps);
 
 	intel_gt_debugfs_register(gt);
+	intel_gt_sysfs_register(gt);
 }
 
 static int intel_gt_init_scratch(struct intel_gt *gt, unsigned int size)
diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt.c b/drivers/gpu/drm/i915/gt/sysfs_gt.c
new file mode 100644
index 000000000000..46cf033a53ec
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/sysfs_gt.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include <drm/drm_device.h>
+#include <linux/device.h>
+#include <linux/kobject.h>
+#include <linux/printk.h>
+#include <linux/sysfs.h>
+
+#include "i915_drv.h"
+#include "i915_sysfs.h"
+#include "intel_gt.h"
+#include "intel_gt_types.h"
+#include "intel_rc6.h"
+
+#include "sysfs_gt.h"
+#include "sysfs_gt_pm.h"
+
+struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
+					    const char *name)
+{
+	struct kobject *kobj = &dev->kobj;
+
+	/*
+	 * We are interested at knowing from where the interface
+	 * has been called, whether it's called from gt/ or from
+	 * the parent directory.
+	 * From the interface position it depends also the value of
+	 * the private data.
+	 * If the interface is called from gt/ then private data is
+	 * of the "struct intel_gt *" type, otherwise it's * a
+	 * "struct drm_i915_private *" type.
+	 */
+	if (!is_object_gt(kobj)) {
+		struct drm_i915_private *i915 = kdev_minor_to_i915(dev);
+
+		pr_devel_ratelimited(DEPRECATED
+			"%s (pid %d) is trying to access deprecated %s "
+			"sysfs control, please use gt/gt<n>/%s instead\n",
+			current->comm, task_pid_nr(current), name, name);
+		return to_gt(i915);
+	}
+
+	return kobj_to_gt(kobj);
+}
+
+static struct kobject *gt_get_parent_obj(struct intel_gt *gt)
+{
+	return &gt->i915->drm.primary->kdev->kobj;
+}
+
+static ssize_t id_show(struct device *dev,
+		       struct device_attribute *attr,
+		       char *buf)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+
+	return sysfs_emit(buf, "%u\n", gt->info.id);
+}
+
+static DEVICE_ATTR_RO(id);
+
+static void kobj_gt_release(struct kobject *kobj)
+{
+	kfree(kobj);
+}
+
+static struct kobj_type kobj_gt_type = {
+	.release = kobj_gt_release,
+	.sysfs_ops = &kobj_sysfs_ops
+};
+
+struct kobject *
+intel_gt_create_kobj(struct intel_gt *gt, struct kobject *dir, const char *name)
+{
+	struct kobj_gt *kg;
+
+	kg = kzalloc(sizeof(*kg), GFP_KERNEL);
+	if (!kg)
+		return NULL;
+
+	kobject_init(&kg->base, &kobj_gt_type);
+	kg->gt = gt;
+
+	/* xfer ownership to sysfs tree */
+	if (kobject_add(&kg->base, dir, "%s", name)) {
+		kobject_put(&kg->base);
+		return NULL;
+	}
+
+	return &kg->base; /* borrowed ref */
+}
+
+void intel_gt_sysfs_register(struct intel_gt *gt)
+{
+	struct kobject *dir;
+	char name[80];
+
+	/*
+	 * We need to make things right with the
+	 * ABI compatibility. The files were originally
+	 * generated under the parent directory.
+	 *
+	 * We generate the files only for gt 0
+	 * to avoid duplicates.
+	 */
+	if (!gt->info.id)
+		intel_gt_sysfs_pm_init(gt, gt_get_parent_obj(gt));
+
+	snprintf(name, sizeof(name), "gt%d", gt->info.id);
+
+	dir = intel_gt_create_kobj(gt, gt->i915->sysfs_gt, name);
+	if (!dir) {
+		drm_err(&gt->i915->drm,
+			"failed to initialize %s sysfs root\n", name);
+		return;
+	}
+
+	if (sysfs_create_file(dir, &dev_attr_id.attr))
+		drm_err(&gt->i915->drm,
+			"failed to create sysfs %s info files\n", name);
+
+	intel_gt_sysfs_pm_init(gt, dir);
+}
diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt.h b/drivers/gpu/drm/i915/gt/sysfs_gt.h
new file mode 100644
index 000000000000..cd80a14bb14d
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/sysfs_gt.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#ifndef __SYSFS_GT_H__
+#define __SYSFS_GT_H__
+
+#include <linux/ctype.h>
+#include <linux/kobject.h>
+
+#include "i915_gem.h" /* GEM_BUG_ON() */
+
+struct intel_gt;
+
+struct kobj_gt {
+	struct kobject base;
+	struct intel_gt *gt;
+};
+
+static inline bool is_object_gt(struct kobject *kobj)
+{
+	bool b = !strncmp(kobj->name, "gt", 2);
+
+	GEM_BUG_ON(b && !isdigit(kobj->name[2]));
+
+	return b;
+}
+
+struct kobject *
+intel_gt_create_kobj(struct intel_gt *gt,
+		     struct kobject *dir,
+		     const char *name);
+
+static inline struct intel_gt *kobj_to_gt(struct kobject *kobj)
+{
+	return container_of(kobj, struct kobj_gt, base)->gt;
+}
+
+void intel_gt_sysfs_register(struct intel_gt *gt);
+struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
+					    const char *name);
+
+#endif /* SYSFS_GT_H */
diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt_pm.c b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
new file mode 100644
index 000000000000..6f4424be42d1
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
@@ -0,0 +1,393 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include <drm/drm_device.h>
+#include <linux/sysfs.h>
+#include <linux/printk.h>
+
+#include "i915_drv.h"
+#include "intel_gt.h"
+#include "intel_rc6.h"
+#include "intel_rps.h"
+#include "sysfs_gt.h"
+#include "sysfs_gt_pm.h"
+
+#ifdef CONFIG_PM
+static u32 get_residency(struct intel_gt *gt, i915_reg_t reg)
+{
+	intel_wakeref_t wakeref;
+	u64 res = 0;
+
+	with_intel_runtime_pm(gt->uncore->rpm, wakeref)
+		res = intel_rc6_residency_us(&gt->rc6, reg);
+
+	return DIV_ROUND_CLOSEST_ULL(res, 1000);
+}
+
+static ssize_t rc6_enable_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	u8 mask = 0;
+
+	if (HAS_RC6(gt->i915))
+		mask |= BIT(0);
+	if (HAS_RC6p(gt->i915))
+		mask |= BIT(1);
+	if (HAS_RC6pp(gt->i915))
+		mask |= BIT(2);
+
+	return scnprintf(buff, PAGE_SIZE, "%x\n", mask);
+}
+
+static ssize_t rc6_residency_ms_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	u32 rc6_residency = get_residency(gt, GEN6_GT_GFX_RC6);
+
+	return scnprintf(buff, PAGE_SIZE, "%u\n", rc6_residency);
+}
+
+static ssize_t rc6p_residency_ms_show(struct device *dev,
+				      struct device_attribute *attr,
+				      char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	u32 rc6p_residency = get_residency(gt, GEN6_GT_GFX_RC6p);
+
+	return scnprintf(buff, PAGE_SIZE, "%u\n", rc6p_residency);
+}
+
+static ssize_t rc6pp_residency_ms_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	u32 rc6pp_residency = get_residency(gt, GEN6_GT_GFX_RC6pp);
+
+	return scnprintf(buff, PAGE_SIZE, "%u\n", rc6pp_residency);
+}
+
+static ssize_t media_rc6_residency_ms_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	u32 rc6_residency = get_residency(gt, VLV_GT_MEDIA_RC6);
+
+	return scnprintf(buff, PAGE_SIZE, "%u\n", rc6_residency);
+}
+
+static DEVICE_ATTR_RO(rc6_enable);
+static DEVICE_ATTR_RO(rc6_residency_ms);
+static DEVICE_ATTR_RO(rc6p_residency_ms);
+static DEVICE_ATTR_RO(rc6pp_residency_ms);
+static DEVICE_ATTR_RO(media_rc6_residency_ms);
+
+static struct attribute *rc6_attrs[] = {
+	&dev_attr_rc6_enable.attr,
+	&dev_attr_rc6_residency_ms.attr,
+	NULL
+};
+
+static struct attribute *rc6p_attrs[] = {
+	&dev_attr_rc6p_residency_ms.attr,
+	&dev_attr_rc6pp_residency_ms.attr,
+	NULL
+};
+
+static struct attribute *media_rc6_attrs[] = {
+	&dev_attr_media_rc6_residency_ms.attr,
+	NULL
+};
+
+static const struct attribute_group rc6_attr_group[] = {
+	{ .name = power_group_name, .attrs = rc6_attrs },
+	{ .attrs = rc6_attrs }
+};
+
+static const struct attribute_group rc6p_attr_group[] = {
+	{ .name = power_group_name, .attrs = rc6p_attrs },
+	{ .attrs = rc6p_attrs }
+};
+
+static const struct attribute_group media_rc6_attr_group[] = {
+	{ .name = power_group_name, .attrs = media_rc6_attrs },
+	{ .attrs = media_rc6_attrs }
+};
+
+static int __intel_gt_sysfs_create_group(struct kobject *kobj,
+					 const struct attribute_group *grp)
+{
+	int i = is_object_gt(kobj);
+
+	return i ? sysfs_create_group(kobj, &grp[i]) :
+		   sysfs_merge_group(kobj, &grp[i]);
+}
+
+static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj)
+{
+	int ret;
+
+	if (!HAS_RC6(gt->i915))
+		return;
+
+	ret = __intel_gt_sysfs_create_group(kobj, rc6_attr_group);
+	if (ret)
+		drm_err(&gt->i915->drm,
+			"failed to create gt%u RC6 sysfs files\n", gt->info.id);
+
+	if (HAS_RC6p(gt->i915)) {
+		ret = __intel_gt_sysfs_create_group(kobj, rc6p_attr_group);
+		if (ret)
+			drm_err(&gt->i915->drm,
+				"failed to create gt%u RC6p sysfs files\n",
+				gt->info.id);
+	}
+
+	if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915)) {
+		ret = __intel_gt_sysfs_create_group(kobj, media_rc6_attr_group);
+		if (ret)
+			drm_err(&gt->i915->drm,
+				"failed to create media %u RC6 sysfs files\n",
+				gt->info.id);
+	}
+}
+#else
+static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj)
+{
+}
+#endif /* CONFIG_PM */
+
+static ssize_t act_freq_mhz_show(struct device *dev,
+				 struct device_attribute *attr, char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+
+	return scnprintf(buff, PAGE_SIZE, "%d\n",
+			intel_rps_read_actual_frequency(&gt->rps));
+}
+
+static ssize_t cur_freq_mhz_show(struct device *dev,
+				 struct device_attribute *attr, char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+
+	return scnprintf(buff, PAGE_SIZE, "%d\n",
+			 intel_rps_get_requested_frequency(rps));
+}
+
+static ssize_t boost_freq_mhz_show(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+
+	return scnprintf(buff, PAGE_SIZE, "%d\n",
+			 intel_rps_get_boost_frequency(rps));
+}
+
+static ssize_t boost_freq_mhz_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buff, size_t count)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+	bool boost = false;
+	ssize_t ret;
+	u32 val;
+
+	ret = kstrtou32(buff, 0, &val);
+	if (ret)
+		return ret;
+
+	/* Validate against (static) hardware limits */
+	val = intel_freq_opcode(rps, val);
+	if (val < rps->min_freq || val > rps->max_freq)
+		return -EINVAL;
+
+	mutex_lock(&rps->lock);
+	if (val != rps->boost_freq) {
+		rps->boost_freq = val;
+		boost = atomic_read(&rps->num_waiters);
+	}
+	mutex_unlock(&rps->lock);
+	if (boost)
+		schedule_work(&rps->work);
+
+	return count;
+}
+
+static ssize_t vlv_rpe_freq_mhz_show(struct device *dev,
+				     struct device_attribute *attr, char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+
+	return scnprintf(buff, PAGE_SIZE, "%d\n",
+			intel_gpu_freq(rps, rps->efficient_freq));
+}
+
+static ssize_t max_freq_mhz_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+
+	return sysfs_emit(buff, "%d\n", intel_rps_get_max_frequency(rps));
+}
+
+static ssize_t max_freq_mhz_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buff, size_t count)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+	ssize_t ret;
+	u32 val;
+
+	ret = kstrtou32(buff, 0, &val);
+	if (ret)
+		return ret;
+
+	ret = intel_rps_set_max_frequency(rps, val);
+
+	return ret ?: count;
+}
+
+static ssize_t min_freq_mhz_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+
+	return sysfs_emit(buff, "%d\n", intel_rps_get_min_frequency(rps));
+}
+
+static ssize_t min_freq_mhz_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buff, size_t count)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+	ssize_t ret;
+	u32 val;
+
+	ret = kstrtou32(buff, 0, &val);
+	if (ret)
+		return ret;
+
+	ret = intel_rps_set_min_frequency(rps, val);
+
+	return ret ?: count;
+}
+
+#define INTEL_GT_RPS_SYSFS_ATTR(_name, _mode, _show, _store) \
+	struct device_attribute dev_attr_gt_##_name = __ATTR(gt_##_name, _mode, _show, _store); \
+	struct device_attribute dev_attr_rps_##_name = __ATTR(rps_##_name, _mode, _show, _store)
+
+#define INTEL_GT_RPS_SYSFS_ATTR_RO(_name)				\
+		INTEL_GT_RPS_SYSFS_ATTR(_name, 0444, _name##_show, NULL)
+#define INTEL_GT_RPS_SYSFS_ATTR_RW(_name)				\
+		INTEL_GT_RPS_SYSFS_ATTR(_name, 0644, _name##_show, _name##_store)
+
+static INTEL_GT_RPS_SYSFS_ATTR_RO(act_freq_mhz);
+static INTEL_GT_RPS_SYSFS_ATTR_RO(cur_freq_mhz);
+static INTEL_GT_RPS_SYSFS_ATTR_RW(boost_freq_mhz);
+static INTEL_GT_RPS_SYSFS_ATTR_RW(max_freq_mhz);
+static INTEL_GT_RPS_SYSFS_ATTR_RW(min_freq_mhz);
+
+static DEVICE_ATTR_RO(vlv_rpe_freq_mhz);
+
+static ssize_t rps_rp_mhz_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buff);
+
+static INTEL_GT_RPS_SYSFS_ATTR(RP0_freq_mhz, 0444, rps_rp_mhz_show, NULL);
+static INTEL_GT_RPS_SYSFS_ATTR(RP1_freq_mhz, 0444, rps_rp_mhz_show, NULL);
+static INTEL_GT_RPS_SYSFS_ATTR(RPn_freq_mhz, 0444, rps_rp_mhz_show, NULL);
+
+#define GEN6_ATTR(s) { \
+		&dev_attr_##s##_act_freq_mhz.attr, \
+		&dev_attr_##s##_cur_freq_mhz.attr, \
+		&dev_attr_##s##_boost_freq_mhz.attr, \
+		&dev_attr_##s##_max_freq_mhz.attr, \
+		&dev_attr_##s##_min_freq_mhz.attr, \
+		&dev_attr_##s##_RP0_freq_mhz.attr, \
+		&dev_attr_##s##_RP1_freq_mhz.attr, \
+		&dev_attr_##s##_RPn_freq_mhz.attr, \
+		NULL, \
+	}
+
+#define GEN6_RPS_ATTR GEN6_ATTR(rps)
+#define GEN6_GT_ATTR  GEN6_ATTR(gt)
+
+/* For now we have a static number of RP states */
+static ssize_t rps_rp_mhz_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+	u32 val;
+
+	if (attr == &dev_attr_gt_RP0_freq_mhz ||
+	    attr == &dev_attr_rps_RP0_freq_mhz) {
+		val = intel_rps_get_rp0_frequency(rps);
+	} else if (attr == &dev_attr_gt_RP1_freq_mhz ||
+		   attr == &dev_attr_rps_RP1_freq_mhz) {
+		   val = intel_rps_get_rp1_frequency(rps);
+	} else if (attr == &dev_attr_gt_RPn_freq_mhz ||
+		   attr == &dev_attr_rps_RPn_freq_mhz) {
+		   val = intel_rps_get_rpn_frequency(rps);
+	} else {
+		GEM_WARN_ON(1);
+		return -ENODEV;
+	}
+
+	return scnprintf(buff, PAGE_SIZE, "%d\n", val);
+}
+
+static const struct attribute * const gen6_rps_attrs[] = GEN6_RPS_ATTR;
+static const struct attribute * const gen6_gt_attrs[]  = GEN6_GT_ATTR;
+
+static int intel_sysfs_rps_init(struct intel_gt *gt, struct kobject *kobj,
+				const struct attribute * const *attrs)
+{
+	int ret;
+
+	if (GRAPHICS_VER(gt->i915) < 6)
+		return 0;
+
+	ret = sysfs_create_files(kobj, attrs);
+	if (ret)
+		return ret;
+
+	if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915))
+		ret = sysfs_create_file(kobj, &dev_attr_vlv_rpe_freq_mhz.attr);
+
+	return ret;
+}
+
+void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj)
+{
+	int ret;
+
+	intel_sysfs_rc6_init(gt, kobj);
+
+	ret = is_object_gt(kobj) ?
+	      intel_sysfs_rps_init(gt, kobj, gen6_rps_attrs) :
+	      intel_sysfs_rps_init(gt, kobj, gen6_gt_attrs);
+	if (ret)
+		drm_err(&gt->i915->drm,
+			"failed to create gt%u RPS sysfs files", gt->info.id);
+}
diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt_pm.h b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.h
new file mode 100644
index 000000000000..18c60d929e6d
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#ifndef __SYSFS_GT_PM_H__
+#define __SYSFS_GT_PM_H__
+
+#include <linux/kobject.h>
+
+#include "intel_gt_types.h"
+
+void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj);
+void intel_gt_sysfs_pm_remove(struct intel_gt *gt, struct kobject *kobj);
+
+#endif /* SYSFS_RC6_H */
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ec76011366fb..f11acbc0990b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -989,6 +989,8 @@ struct drm_i915_private {
 #define I915_MAX_GT 4
 	struct intel_gt *gt[I915_MAX_GT];
 
+	struct kobject *sysfs_gt;
+
 	struct {
 		struct i915_gem_contexts {
 			spinlock_t lock; /* locks list */
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ef6bc8180073..5153b3ff41e9 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -8480,6 +8480,7 @@ enum {
 #define   GEN6_AGGRESSIVE_TURBO			(0 << 15)
 #define   GEN9_SW_REQ_UNSLICE_RATIO_SHIFT	23
 #define   GEN9_IGNORE_SLICE_RATIO		(0 << 0)
+#define   GEN12_SW_REQ_UNSLICE_RATIO_SHIFT	23
 
 #define GEN6_RC_VIDEO_FREQ			_MMIO(0xA00C)
 #define GEN6_RC_CONTROL				_MMIO(0xA090)
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index fae4d1f4f275..d6687e33f29d 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -38,113 +38,12 @@
 #include "i915_sysfs.h"
 #include "intel_pm.h"
 
-static inline struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
+struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
 {
 	struct drm_minor *minor = dev_get_drvdata(kdev);
 	return to_i915(minor->dev);
 }
 
-#ifdef CONFIG_PM
-static u32 calc_residency(struct drm_i915_private *dev_priv,
-			  i915_reg_t reg)
-{
-	intel_wakeref_t wakeref;
-	u64 res = 0;
-
-	with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref)
-		res = intel_rc6_residency_us(&to_gt(dev_priv)->rc6, reg);
-
-	return DIV_ROUND_CLOSEST_ULL(res, 1000);
-}
-
-static ssize_t rc6_enable_show(struct device *kdev,
-			       struct device_attribute *attr, char *buf)
-{
-	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	unsigned int mask;
-
-	mask = 0;
-	if (HAS_RC6(dev_priv))
-		mask |= BIT(0);
-	if (HAS_RC6p(dev_priv))
-		mask |= BIT(1);
-	if (HAS_RC6pp(dev_priv))
-		mask |= BIT(2);
-
-	return sysfs_emit(buf, "%x\n", mask);
-}
-
-static ssize_t rc6_residency_ms_show(struct device *kdev,
-				     struct device_attribute *attr, char *buf)
-{
-	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	u32 rc6_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6);
-	return sysfs_emit(buf, "%u\n", rc6_residency);
-}
-
-static ssize_t rc6p_residency_ms_show(struct device *kdev,
-				      struct device_attribute *attr, char *buf)
-{
-	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	u32 rc6p_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6p);
-	return sysfs_emit(buf, "%u\n", rc6p_residency);
-}
-
-static ssize_t rc6pp_residency_ms_show(struct device *kdev,
-				       struct device_attribute *attr, char *buf)
-{
-	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	u32 rc6pp_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6pp);
-	return sysfs_emit(buf, "%u\n", rc6pp_residency);
-}
-
-static ssize_t media_rc6_residency_ms_show(struct device *kdev,
-					   struct device_attribute *attr, char *buf)
-{
-	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	u32 rc6_residency = calc_residency(dev_priv, VLV_GT_MEDIA_RC6);
-	return sysfs_emit(buf, "%u\n", rc6_residency);
-}
-
-static DEVICE_ATTR_RO(rc6_enable);
-static DEVICE_ATTR_RO(rc6_residency_ms);
-static DEVICE_ATTR_RO(rc6p_residency_ms);
-static DEVICE_ATTR_RO(rc6pp_residency_ms);
-static DEVICE_ATTR_RO(media_rc6_residency_ms);
-
-static struct attribute *rc6_attrs[] = {
-	&dev_attr_rc6_enable.attr,
-	&dev_attr_rc6_residency_ms.attr,
-	NULL
-};
-
-static const struct attribute_group rc6_attr_group = {
-	.name = power_group_name,
-	.attrs =  rc6_attrs
-};
-
-static struct attribute *rc6p_attrs[] = {
-	&dev_attr_rc6p_residency_ms.attr,
-	&dev_attr_rc6pp_residency_ms.attr,
-	NULL
-};
-
-static const struct attribute_group rc6p_attr_group = {
-	.name = power_group_name,
-	.attrs =  rc6p_attrs
-};
-
-static struct attribute *media_rc6_attrs[] = {
-	&dev_attr_media_rc6_residency_ms.attr,
-	NULL
-};
-
-static const struct attribute_group media_rc6_attr_group = {
-	.name = power_group_name,
-	.attrs =  media_rc6_attrs
-};
-#endif
-
 static int l3_access_valid(struct drm_i915_private *i915, loff_t offset)
 {
 	if (!HAS_L3_DPF(i915))
@@ -256,171 +155,6 @@ static const struct bin_attribute dpf_attrs_1 = {
 	.private = (void *)1
 };
 
-static ssize_t gt_act_freq_mhz_show(struct device *kdev,
-				    struct device_attribute *attr, char *buf)
-{
-	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
-	struct intel_rps *rps = &to_gt(i915)->rps;
-
-	return sysfs_emit(buf, "%d\n", intel_rps_read_actual_frequency(rps));
-}
-
-static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
-				    struct device_attribute *attr, char *buf)
-{
-	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
-	struct intel_rps *rps = &to_gt(i915)->rps;
-
-	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)
-{
-	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
-	struct intel_rps *rps = &to_gt(i915)->rps;
-
-	return sysfs_emit(buf, "%d\n", intel_rps_get_boost_frequency(rps));
-}
-
-static ssize_t gt_boost_freq_mhz_store(struct device *kdev,
-				       struct device_attribute *attr,
-				       const char *buf, size_t count)
-{
-	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	struct intel_rps *rps = &to_gt(dev_priv)->rps;
-	ssize_t ret;
-	u32 val;
-
-	ret = kstrtou32(buf, 0, &val);
-	if (ret)
-		return ret;
-
-	ret = intel_rps_set_boost_frequency(rps, val);
-
-	return ret ?: count;
-}
-
-static ssize_t vlv_rpe_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 = &to_gt(dev_priv)->rps;
-
-	return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->efficient_freq));
-}
-
-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_gt *gt = to_gt(dev_priv);
-	struct intel_rps *rps = &gt->rps;
-
-	return sysfs_emit(buf, "%d\n", intel_rps_get_max_frequency(rps));
-}
-
-static ssize_t gt_max_freq_mhz_store(struct device *kdev,
-				     struct device_attribute *attr,
-				     const char *buf, size_t count)
-{
-	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	struct intel_gt *gt = to_gt(dev_priv);
-	struct intel_rps *rps = &gt->rps;
-	ssize_t ret;
-	u32 val;
-
-	ret = kstrtou32(buf, 0, &val);
-	if (ret)
-		return ret;
-
-	ret = intel_rps_set_max_frequency(rps, val);
-
-	return ret ?: count;
-}
-
-static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
-{
-	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
-	struct intel_gt *gt = to_gt(i915);
-	struct intel_rps *rps = &gt->rps;
-
-	return sysfs_emit(buf, "%d\n", intel_rps_get_min_frequency(rps));
-}
-
-static ssize_t gt_min_freq_mhz_store(struct device *kdev,
-				     struct device_attribute *attr,
-				     const char *buf, size_t count)
-{
-	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
-	struct intel_rps *rps = &to_gt(i915)->rps;
-	ssize_t ret;
-	u32 val;
-
-	ret = kstrtou32(buf, 0, &val);
-	if (ret)
-		return ret;
-
-	ret = intel_rps_set_min_frequency(rps, val);
-
-	return ret ?: count;
-}
-
-static DEVICE_ATTR_RO(gt_act_freq_mhz);
-static DEVICE_ATTR_RO(gt_cur_freq_mhz);
-static DEVICE_ATTR_RW(gt_boost_freq_mhz);
-static DEVICE_ATTR_RW(gt_max_freq_mhz);
-static DEVICE_ATTR_RW(gt_min_freq_mhz);
-
-static DEVICE_ATTR_RO(vlv_rpe_freq_mhz);
-
-static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf);
-static DEVICE_ATTR(gt_RP0_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
-static DEVICE_ATTR(gt_RP1_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
-static DEVICE_ATTR(gt_RPn_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
-
-/* For now we have a static number of RP states */
-static ssize_t gt_rp_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 = &to_gt(dev_priv)->rps;
-	u32 val;
-
-	if (attr == &dev_attr_gt_RP0_freq_mhz)
-		val = intel_rps_get_rp0_frequency(rps);
-	else if (attr == &dev_attr_gt_RP1_freq_mhz)
-		val = intel_rps_get_rp1_frequency(rps);
-	else if (attr == &dev_attr_gt_RPn_freq_mhz)
-		val = intel_rps_get_rpn_frequency(rps);
-	else
-		BUG();
-
-	return sysfs_emit(buf, "%d\n", val);
-}
-
-static const struct attribute * const gen6_attrs[] = {
-	&dev_attr_gt_act_freq_mhz.attr,
-	&dev_attr_gt_cur_freq_mhz.attr,
-	&dev_attr_gt_boost_freq_mhz.attr,
-	&dev_attr_gt_max_freq_mhz.attr,
-	&dev_attr_gt_min_freq_mhz.attr,
-	&dev_attr_gt_RP0_freq_mhz.attr,
-	&dev_attr_gt_RP1_freq_mhz.attr,
-	&dev_attr_gt_RPn_freq_mhz.attr,
-	NULL,
-};
-
-static const struct attribute * const vlv_attrs[] = {
-	&dev_attr_gt_act_freq_mhz.attr,
-	&dev_attr_gt_cur_freq_mhz.attr,
-	&dev_attr_gt_boost_freq_mhz.attr,
-	&dev_attr_gt_max_freq_mhz.attr,
-	&dev_attr_gt_min_freq_mhz.attr,
-	&dev_attr_gt_RP0_freq_mhz.attr,
-	&dev_attr_gt_RP1_freq_mhz.attr,
-	&dev_attr_gt_RPn_freq_mhz.attr,
-	&dev_attr_vlv_rpe_freq_mhz.attr,
-	NULL,
-};
-
 #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
 
 static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
@@ -486,34 +220,16 @@ static void i915_setup_error_capture(struct device *kdev) {}
 static void i915_teardown_error_capture(struct device *kdev) {}
 #endif
 
+static struct kobject *i915_setup_gt_sysfs(struct kobject *parent)
+{
+	return kobject_create_and_add("gt", parent);
+}
+
 void i915_setup_sysfs(struct drm_i915_private *dev_priv)
 {
 	struct device *kdev = dev_priv->drm.primary->kdev;
 	int ret;
 
-#ifdef CONFIG_PM
-	if (HAS_RC6(dev_priv)) {
-		ret = sysfs_merge_group(&kdev->kobj,
-					&rc6_attr_group);
-		if (ret)
-			drm_err(&dev_priv->drm,
-				"RC6 residency sysfs setup failed\n");
-	}
-	if (HAS_RC6p(dev_priv)) {
-		ret = sysfs_merge_group(&kdev->kobj,
-					&rc6p_attr_group);
-		if (ret)
-			drm_err(&dev_priv->drm,
-				"RC6p residency sysfs setup failed\n");
-	}
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-		ret = sysfs_merge_group(&kdev->kobj,
-					&media_rc6_attr_group);
-		if (ret)
-			drm_err(&dev_priv->drm,
-				"Media RC6 residency sysfs setup failed\n");
-	}
-#endif
 	if (HAS_L3_DPF(dev_priv)) {
 		ret = device_create_bin_file(kdev, &dpf_attrs);
 		if (ret)
@@ -529,13 +245,10 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv)
 		}
 	}
 
-	ret = 0;
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		ret = sysfs_create_files(&kdev->kobj, vlv_attrs);
-	else if (GRAPHICS_VER(dev_priv) >= 6)
-		ret = sysfs_create_files(&kdev->kobj, gen6_attrs);
-	if (ret)
-		drm_err(&dev_priv->drm, "RPS sysfs setup failed\n");
+	dev_priv->sysfs_gt = i915_setup_gt_sysfs(&kdev->kobj);
+	if (!dev_priv->sysfs_gt)
+		drm_err(&dev_priv->drm,
+			"failed to register GT sysfs directory\n");
 
 	i915_setup_error_capture(kdev);
 
@@ -548,14 +261,6 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv)
 
 	i915_teardown_error_capture(kdev);
 
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		sysfs_remove_files(&kdev->kobj, vlv_attrs);
-	else
-		sysfs_remove_files(&kdev->kobj, gen6_attrs);
 	device_remove_bin_file(kdev,  &dpf_attrs_1);
 	device_remove_bin_file(kdev,  &dpf_attrs);
-#ifdef CONFIG_PM
-	sysfs_unmerge_group(&kdev->kobj, &rc6_attr_group);
-	sysfs_unmerge_group(&kdev->kobj, &rc6p_attr_group);
-#endif
 }
diff --git a/drivers/gpu/drm/i915/i915_sysfs.h b/drivers/gpu/drm/i915/i915_sysfs.h
index 41afd4366416..243a17741e3f 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.h
+++ b/drivers/gpu/drm/i915/i915_sysfs.h
@@ -6,8 +6,11 @@
 #ifndef __I915_SYSFS_H__
 #define __I915_SYSFS_H__
 
+struct device;
 struct drm_i915_private;
 
+struct drm_i915_private *kdev_minor_to_i915(struct device *kdev);
+
 void i915_setup_sysfs(struct drm_i915_private *i915);
 void i915_teardown_sysfs(struct drm_i915_private *i915);
 
-- 
2.34.1


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

* [Intel-gfx] [PATCH v3 2/2] drm/i915/gt: make a gt sysfs group and move power management files
@ 2022-01-17 15:09   ` Andi Shyti
  0 siblings, 0 replies; 17+ messages in thread
From: Andi Shyti @ 2022-01-17 15:09 UTC (permalink / raw)
  To: Intel GFX, DRI Devel; +Cc: Abdiel Janulgue, Lucas De Marchi, Matthew Auld

The GT has its own properties and in sysfs they should be grouped
in the 'gt/' directory.

Create a 'gt/' directory in sysfs which will contain gt0...gtN
directories related to each tile configured in the GPU. Move the
power management files inside those directories.

The previous power management files are kept in their original
root directory to avoid breaking the ABI. They point to the tile
'0' and a warning message is printed whenever accessed to. The
deprecated interface needs for the CONFIG_SYSFS_DEPRECATED_V2
flag in order to be generated.

The new sysfs structure will have a similar layout for the 4 tile
case:

/sys/.../card0
         ├── gt
         │   ├── gt0
         │   │   ├── id
         │   │   ├── rc6_enable
         │   │   ├── rc6_residency_ms
         │   │   ├── rps_act_freq_mhz
         │   │   ├── rps_boost_freq_mhz
         │   │   ├── rps_cur_freq_mhz
         │   │   ├── rps_max_freq_mhz
         │   │   ├── rps_min_freq_mhz
         │   │   ├── rps_RP0_freq_mhz
         │   │   ├── rps_RP1_freq_mhz
         │   │   └── rps_RPn_freq_mhz
	 .   .
	 .   .
	 .   .
         │   └── gt3
         │       ├── id
         │       ├── rc6_enable
         │       ├── rc6_residency_ms
         │       ├── rps_act_freq_mhz
         │       ├── rps_boost_freq_mhz
         │       ├── rps_cur_freq_mhz
         │       ├── rps_max_freq_mhz
         │       ├── rps_min_freq_mhz
         │       ├── rps_RP0_freq_mhz
         │       ├── rps_RP1_freq_mhz
         │       └── rps_RPn_freq_mhz
         ├── gt_act_freq_mhz   -+
         ├── gt_boost_freq_mhz  |
         ├── gt_cur_freq_mhz    |    Original interface
         ├── gt_max_freq_mhz    +─-> kept as existing ABI;
         ├── gt_min_freq_mhz    |    it points to gt0/
         ├── gt_RP0_freq_mhz    |
         └── gt_RP1_freq_mhz    |
         └── gt_RPn_freq_mhz   -+

As soon as multitile platforms will start being supported, this
interface will allow to control the power (either manually or
with tools) on each tile, instead of affecting only tile 0 and
getting incomplete results.

Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
Cc: Matt Roper <matthew.d.roper@intel.com>
Cc: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
---
 drivers/gpu/drm/i915/Makefile         |   4 +-
 drivers/gpu/drm/i915/gt/intel_gt.c    |   2 +
 drivers/gpu/drm/i915/gt/sysfs_gt.c    | 126 +++++++++
 drivers/gpu/drm/i915/gt/sysfs_gt.h    |  44 +++
 drivers/gpu/drm/i915/gt/sysfs_gt_pm.c | 393 ++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gt/sysfs_gt_pm.h |  16 ++
 drivers/gpu/drm/i915/i915_drv.h       |   2 +
 drivers/gpu/drm/i915/i915_reg.h       |   1 +
 drivers/gpu/drm/i915/i915_sysfs.c     | 315 +--------------------
 drivers/gpu/drm/i915/i915_sysfs.h     |   3 +
 10 files changed, 600 insertions(+), 306 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt.c
 create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt.h
 create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
 create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt_pm.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index aa86ac33effc..5fd203c626fc 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -121,7 +121,9 @@ gt-y += \
 	gt/intel_timeline.o \
 	gt/intel_workarounds.o \
 	gt/shmem_utils.o \
-	gt/sysfs_engines.o
+	gt/sysfs_engines.o \
+	gt/sysfs_gt.o \
+	gt/sysfs_gt_pm.o
 # autogenerated null render state
 gt-y += \
 	gt/gen6_renderstate.o \
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
index 17927da9e23e..2584c51c1c14 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -25,6 +25,7 @@
 #include "intel_rps.h"
 #include "intel_uncore.h"
 #include "shmem_utils.h"
+#include "sysfs_gt.h"
 #include "pxp/intel_pxp.h"
 
 static void
@@ -453,6 +454,7 @@ void intel_gt_driver_register(struct intel_gt *gt)
 	intel_rps_driver_register(&gt->rps);
 
 	intel_gt_debugfs_register(gt);
+	intel_gt_sysfs_register(gt);
 }
 
 static int intel_gt_init_scratch(struct intel_gt *gt, unsigned int size)
diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt.c b/drivers/gpu/drm/i915/gt/sysfs_gt.c
new file mode 100644
index 000000000000..46cf033a53ec
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/sysfs_gt.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include <drm/drm_device.h>
+#include <linux/device.h>
+#include <linux/kobject.h>
+#include <linux/printk.h>
+#include <linux/sysfs.h>
+
+#include "i915_drv.h"
+#include "i915_sysfs.h"
+#include "intel_gt.h"
+#include "intel_gt_types.h"
+#include "intel_rc6.h"
+
+#include "sysfs_gt.h"
+#include "sysfs_gt_pm.h"
+
+struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
+					    const char *name)
+{
+	struct kobject *kobj = &dev->kobj;
+
+	/*
+	 * We are interested at knowing from where the interface
+	 * has been called, whether it's called from gt/ or from
+	 * the parent directory.
+	 * From the interface position it depends also the value of
+	 * the private data.
+	 * If the interface is called from gt/ then private data is
+	 * of the "struct intel_gt *" type, otherwise it's * a
+	 * "struct drm_i915_private *" type.
+	 */
+	if (!is_object_gt(kobj)) {
+		struct drm_i915_private *i915 = kdev_minor_to_i915(dev);
+
+		pr_devel_ratelimited(DEPRECATED
+			"%s (pid %d) is trying to access deprecated %s "
+			"sysfs control, please use gt/gt<n>/%s instead\n",
+			current->comm, task_pid_nr(current), name, name);
+		return to_gt(i915);
+	}
+
+	return kobj_to_gt(kobj);
+}
+
+static struct kobject *gt_get_parent_obj(struct intel_gt *gt)
+{
+	return &gt->i915->drm.primary->kdev->kobj;
+}
+
+static ssize_t id_show(struct device *dev,
+		       struct device_attribute *attr,
+		       char *buf)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+
+	return sysfs_emit(buf, "%u\n", gt->info.id);
+}
+
+static DEVICE_ATTR_RO(id);
+
+static void kobj_gt_release(struct kobject *kobj)
+{
+	kfree(kobj);
+}
+
+static struct kobj_type kobj_gt_type = {
+	.release = kobj_gt_release,
+	.sysfs_ops = &kobj_sysfs_ops
+};
+
+struct kobject *
+intel_gt_create_kobj(struct intel_gt *gt, struct kobject *dir, const char *name)
+{
+	struct kobj_gt *kg;
+
+	kg = kzalloc(sizeof(*kg), GFP_KERNEL);
+	if (!kg)
+		return NULL;
+
+	kobject_init(&kg->base, &kobj_gt_type);
+	kg->gt = gt;
+
+	/* xfer ownership to sysfs tree */
+	if (kobject_add(&kg->base, dir, "%s", name)) {
+		kobject_put(&kg->base);
+		return NULL;
+	}
+
+	return &kg->base; /* borrowed ref */
+}
+
+void intel_gt_sysfs_register(struct intel_gt *gt)
+{
+	struct kobject *dir;
+	char name[80];
+
+	/*
+	 * We need to make things right with the
+	 * ABI compatibility. The files were originally
+	 * generated under the parent directory.
+	 *
+	 * We generate the files only for gt 0
+	 * to avoid duplicates.
+	 */
+	if (!gt->info.id)
+		intel_gt_sysfs_pm_init(gt, gt_get_parent_obj(gt));
+
+	snprintf(name, sizeof(name), "gt%d", gt->info.id);
+
+	dir = intel_gt_create_kobj(gt, gt->i915->sysfs_gt, name);
+	if (!dir) {
+		drm_err(&gt->i915->drm,
+			"failed to initialize %s sysfs root\n", name);
+		return;
+	}
+
+	if (sysfs_create_file(dir, &dev_attr_id.attr))
+		drm_err(&gt->i915->drm,
+			"failed to create sysfs %s info files\n", name);
+
+	intel_gt_sysfs_pm_init(gt, dir);
+}
diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt.h b/drivers/gpu/drm/i915/gt/sysfs_gt.h
new file mode 100644
index 000000000000..cd80a14bb14d
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/sysfs_gt.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#ifndef __SYSFS_GT_H__
+#define __SYSFS_GT_H__
+
+#include <linux/ctype.h>
+#include <linux/kobject.h>
+
+#include "i915_gem.h" /* GEM_BUG_ON() */
+
+struct intel_gt;
+
+struct kobj_gt {
+	struct kobject base;
+	struct intel_gt *gt;
+};
+
+static inline bool is_object_gt(struct kobject *kobj)
+{
+	bool b = !strncmp(kobj->name, "gt", 2);
+
+	GEM_BUG_ON(b && !isdigit(kobj->name[2]));
+
+	return b;
+}
+
+struct kobject *
+intel_gt_create_kobj(struct intel_gt *gt,
+		     struct kobject *dir,
+		     const char *name);
+
+static inline struct intel_gt *kobj_to_gt(struct kobject *kobj)
+{
+	return container_of(kobj, struct kobj_gt, base)->gt;
+}
+
+void intel_gt_sysfs_register(struct intel_gt *gt);
+struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
+					    const char *name);
+
+#endif /* SYSFS_GT_H */
diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt_pm.c b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
new file mode 100644
index 000000000000..6f4424be42d1
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
@@ -0,0 +1,393 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include <drm/drm_device.h>
+#include <linux/sysfs.h>
+#include <linux/printk.h>
+
+#include "i915_drv.h"
+#include "intel_gt.h"
+#include "intel_rc6.h"
+#include "intel_rps.h"
+#include "sysfs_gt.h"
+#include "sysfs_gt_pm.h"
+
+#ifdef CONFIG_PM
+static u32 get_residency(struct intel_gt *gt, i915_reg_t reg)
+{
+	intel_wakeref_t wakeref;
+	u64 res = 0;
+
+	with_intel_runtime_pm(gt->uncore->rpm, wakeref)
+		res = intel_rc6_residency_us(&gt->rc6, reg);
+
+	return DIV_ROUND_CLOSEST_ULL(res, 1000);
+}
+
+static ssize_t rc6_enable_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	u8 mask = 0;
+
+	if (HAS_RC6(gt->i915))
+		mask |= BIT(0);
+	if (HAS_RC6p(gt->i915))
+		mask |= BIT(1);
+	if (HAS_RC6pp(gt->i915))
+		mask |= BIT(2);
+
+	return scnprintf(buff, PAGE_SIZE, "%x\n", mask);
+}
+
+static ssize_t rc6_residency_ms_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	u32 rc6_residency = get_residency(gt, GEN6_GT_GFX_RC6);
+
+	return scnprintf(buff, PAGE_SIZE, "%u\n", rc6_residency);
+}
+
+static ssize_t rc6p_residency_ms_show(struct device *dev,
+				      struct device_attribute *attr,
+				      char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	u32 rc6p_residency = get_residency(gt, GEN6_GT_GFX_RC6p);
+
+	return scnprintf(buff, PAGE_SIZE, "%u\n", rc6p_residency);
+}
+
+static ssize_t rc6pp_residency_ms_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	u32 rc6pp_residency = get_residency(gt, GEN6_GT_GFX_RC6pp);
+
+	return scnprintf(buff, PAGE_SIZE, "%u\n", rc6pp_residency);
+}
+
+static ssize_t media_rc6_residency_ms_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	u32 rc6_residency = get_residency(gt, VLV_GT_MEDIA_RC6);
+
+	return scnprintf(buff, PAGE_SIZE, "%u\n", rc6_residency);
+}
+
+static DEVICE_ATTR_RO(rc6_enable);
+static DEVICE_ATTR_RO(rc6_residency_ms);
+static DEVICE_ATTR_RO(rc6p_residency_ms);
+static DEVICE_ATTR_RO(rc6pp_residency_ms);
+static DEVICE_ATTR_RO(media_rc6_residency_ms);
+
+static struct attribute *rc6_attrs[] = {
+	&dev_attr_rc6_enable.attr,
+	&dev_attr_rc6_residency_ms.attr,
+	NULL
+};
+
+static struct attribute *rc6p_attrs[] = {
+	&dev_attr_rc6p_residency_ms.attr,
+	&dev_attr_rc6pp_residency_ms.attr,
+	NULL
+};
+
+static struct attribute *media_rc6_attrs[] = {
+	&dev_attr_media_rc6_residency_ms.attr,
+	NULL
+};
+
+static const struct attribute_group rc6_attr_group[] = {
+	{ .name = power_group_name, .attrs = rc6_attrs },
+	{ .attrs = rc6_attrs }
+};
+
+static const struct attribute_group rc6p_attr_group[] = {
+	{ .name = power_group_name, .attrs = rc6p_attrs },
+	{ .attrs = rc6p_attrs }
+};
+
+static const struct attribute_group media_rc6_attr_group[] = {
+	{ .name = power_group_name, .attrs = media_rc6_attrs },
+	{ .attrs = media_rc6_attrs }
+};
+
+static int __intel_gt_sysfs_create_group(struct kobject *kobj,
+					 const struct attribute_group *grp)
+{
+	int i = is_object_gt(kobj);
+
+	return i ? sysfs_create_group(kobj, &grp[i]) :
+		   sysfs_merge_group(kobj, &grp[i]);
+}
+
+static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj)
+{
+	int ret;
+
+	if (!HAS_RC6(gt->i915))
+		return;
+
+	ret = __intel_gt_sysfs_create_group(kobj, rc6_attr_group);
+	if (ret)
+		drm_err(&gt->i915->drm,
+			"failed to create gt%u RC6 sysfs files\n", gt->info.id);
+
+	if (HAS_RC6p(gt->i915)) {
+		ret = __intel_gt_sysfs_create_group(kobj, rc6p_attr_group);
+		if (ret)
+			drm_err(&gt->i915->drm,
+				"failed to create gt%u RC6p sysfs files\n",
+				gt->info.id);
+	}
+
+	if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915)) {
+		ret = __intel_gt_sysfs_create_group(kobj, media_rc6_attr_group);
+		if (ret)
+			drm_err(&gt->i915->drm,
+				"failed to create media %u RC6 sysfs files\n",
+				gt->info.id);
+	}
+}
+#else
+static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj)
+{
+}
+#endif /* CONFIG_PM */
+
+static ssize_t act_freq_mhz_show(struct device *dev,
+				 struct device_attribute *attr, char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+
+	return scnprintf(buff, PAGE_SIZE, "%d\n",
+			intel_rps_read_actual_frequency(&gt->rps));
+}
+
+static ssize_t cur_freq_mhz_show(struct device *dev,
+				 struct device_attribute *attr, char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+
+	return scnprintf(buff, PAGE_SIZE, "%d\n",
+			 intel_rps_get_requested_frequency(rps));
+}
+
+static ssize_t boost_freq_mhz_show(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+
+	return scnprintf(buff, PAGE_SIZE, "%d\n",
+			 intel_rps_get_boost_frequency(rps));
+}
+
+static ssize_t boost_freq_mhz_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buff, size_t count)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+	bool boost = false;
+	ssize_t ret;
+	u32 val;
+
+	ret = kstrtou32(buff, 0, &val);
+	if (ret)
+		return ret;
+
+	/* Validate against (static) hardware limits */
+	val = intel_freq_opcode(rps, val);
+	if (val < rps->min_freq || val > rps->max_freq)
+		return -EINVAL;
+
+	mutex_lock(&rps->lock);
+	if (val != rps->boost_freq) {
+		rps->boost_freq = val;
+		boost = atomic_read(&rps->num_waiters);
+	}
+	mutex_unlock(&rps->lock);
+	if (boost)
+		schedule_work(&rps->work);
+
+	return count;
+}
+
+static ssize_t vlv_rpe_freq_mhz_show(struct device *dev,
+				     struct device_attribute *attr, char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+
+	return scnprintf(buff, PAGE_SIZE, "%d\n",
+			intel_gpu_freq(rps, rps->efficient_freq));
+}
+
+static ssize_t max_freq_mhz_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+
+	return sysfs_emit(buff, "%d\n", intel_rps_get_max_frequency(rps));
+}
+
+static ssize_t max_freq_mhz_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buff, size_t count)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+	ssize_t ret;
+	u32 val;
+
+	ret = kstrtou32(buff, 0, &val);
+	if (ret)
+		return ret;
+
+	ret = intel_rps_set_max_frequency(rps, val);
+
+	return ret ?: count;
+}
+
+static ssize_t min_freq_mhz_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+
+	return sysfs_emit(buff, "%d\n", intel_rps_get_min_frequency(rps));
+}
+
+static ssize_t min_freq_mhz_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buff, size_t count)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+	ssize_t ret;
+	u32 val;
+
+	ret = kstrtou32(buff, 0, &val);
+	if (ret)
+		return ret;
+
+	ret = intel_rps_set_min_frequency(rps, val);
+
+	return ret ?: count;
+}
+
+#define INTEL_GT_RPS_SYSFS_ATTR(_name, _mode, _show, _store) \
+	struct device_attribute dev_attr_gt_##_name = __ATTR(gt_##_name, _mode, _show, _store); \
+	struct device_attribute dev_attr_rps_##_name = __ATTR(rps_##_name, _mode, _show, _store)
+
+#define INTEL_GT_RPS_SYSFS_ATTR_RO(_name)				\
+		INTEL_GT_RPS_SYSFS_ATTR(_name, 0444, _name##_show, NULL)
+#define INTEL_GT_RPS_SYSFS_ATTR_RW(_name)				\
+		INTEL_GT_RPS_SYSFS_ATTR(_name, 0644, _name##_show, _name##_store)
+
+static INTEL_GT_RPS_SYSFS_ATTR_RO(act_freq_mhz);
+static INTEL_GT_RPS_SYSFS_ATTR_RO(cur_freq_mhz);
+static INTEL_GT_RPS_SYSFS_ATTR_RW(boost_freq_mhz);
+static INTEL_GT_RPS_SYSFS_ATTR_RW(max_freq_mhz);
+static INTEL_GT_RPS_SYSFS_ATTR_RW(min_freq_mhz);
+
+static DEVICE_ATTR_RO(vlv_rpe_freq_mhz);
+
+static ssize_t rps_rp_mhz_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buff);
+
+static INTEL_GT_RPS_SYSFS_ATTR(RP0_freq_mhz, 0444, rps_rp_mhz_show, NULL);
+static INTEL_GT_RPS_SYSFS_ATTR(RP1_freq_mhz, 0444, rps_rp_mhz_show, NULL);
+static INTEL_GT_RPS_SYSFS_ATTR(RPn_freq_mhz, 0444, rps_rp_mhz_show, NULL);
+
+#define GEN6_ATTR(s) { \
+		&dev_attr_##s##_act_freq_mhz.attr, \
+		&dev_attr_##s##_cur_freq_mhz.attr, \
+		&dev_attr_##s##_boost_freq_mhz.attr, \
+		&dev_attr_##s##_max_freq_mhz.attr, \
+		&dev_attr_##s##_min_freq_mhz.attr, \
+		&dev_attr_##s##_RP0_freq_mhz.attr, \
+		&dev_attr_##s##_RP1_freq_mhz.attr, \
+		&dev_attr_##s##_RPn_freq_mhz.attr, \
+		NULL, \
+	}
+
+#define GEN6_RPS_ATTR GEN6_ATTR(rps)
+#define GEN6_GT_ATTR  GEN6_ATTR(gt)
+
+/* For now we have a static number of RP states */
+static ssize_t rps_rp_mhz_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+	struct intel_rps *rps = &gt->rps;
+	u32 val;
+
+	if (attr == &dev_attr_gt_RP0_freq_mhz ||
+	    attr == &dev_attr_rps_RP0_freq_mhz) {
+		val = intel_rps_get_rp0_frequency(rps);
+	} else if (attr == &dev_attr_gt_RP1_freq_mhz ||
+		   attr == &dev_attr_rps_RP1_freq_mhz) {
+		   val = intel_rps_get_rp1_frequency(rps);
+	} else if (attr == &dev_attr_gt_RPn_freq_mhz ||
+		   attr == &dev_attr_rps_RPn_freq_mhz) {
+		   val = intel_rps_get_rpn_frequency(rps);
+	} else {
+		GEM_WARN_ON(1);
+		return -ENODEV;
+	}
+
+	return scnprintf(buff, PAGE_SIZE, "%d\n", val);
+}
+
+static const struct attribute * const gen6_rps_attrs[] = GEN6_RPS_ATTR;
+static const struct attribute * const gen6_gt_attrs[]  = GEN6_GT_ATTR;
+
+static int intel_sysfs_rps_init(struct intel_gt *gt, struct kobject *kobj,
+				const struct attribute * const *attrs)
+{
+	int ret;
+
+	if (GRAPHICS_VER(gt->i915) < 6)
+		return 0;
+
+	ret = sysfs_create_files(kobj, attrs);
+	if (ret)
+		return ret;
+
+	if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915))
+		ret = sysfs_create_file(kobj, &dev_attr_vlv_rpe_freq_mhz.attr);
+
+	return ret;
+}
+
+void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj)
+{
+	int ret;
+
+	intel_sysfs_rc6_init(gt, kobj);
+
+	ret = is_object_gt(kobj) ?
+	      intel_sysfs_rps_init(gt, kobj, gen6_rps_attrs) :
+	      intel_sysfs_rps_init(gt, kobj, gen6_gt_attrs);
+	if (ret)
+		drm_err(&gt->i915->drm,
+			"failed to create gt%u RPS sysfs files", gt->info.id);
+}
diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt_pm.h b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.h
new file mode 100644
index 000000000000..18c60d929e6d
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#ifndef __SYSFS_GT_PM_H__
+#define __SYSFS_GT_PM_H__
+
+#include <linux/kobject.h>
+
+#include "intel_gt_types.h"
+
+void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj);
+void intel_gt_sysfs_pm_remove(struct intel_gt *gt, struct kobject *kobj);
+
+#endif /* SYSFS_RC6_H */
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ec76011366fb..f11acbc0990b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -989,6 +989,8 @@ struct drm_i915_private {
 #define I915_MAX_GT 4
 	struct intel_gt *gt[I915_MAX_GT];
 
+	struct kobject *sysfs_gt;
+
 	struct {
 		struct i915_gem_contexts {
 			spinlock_t lock; /* locks list */
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ef6bc8180073..5153b3ff41e9 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -8480,6 +8480,7 @@ enum {
 #define   GEN6_AGGRESSIVE_TURBO			(0 << 15)
 #define   GEN9_SW_REQ_UNSLICE_RATIO_SHIFT	23
 #define   GEN9_IGNORE_SLICE_RATIO		(0 << 0)
+#define   GEN12_SW_REQ_UNSLICE_RATIO_SHIFT	23
 
 #define GEN6_RC_VIDEO_FREQ			_MMIO(0xA00C)
 #define GEN6_RC_CONTROL				_MMIO(0xA090)
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index fae4d1f4f275..d6687e33f29d 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -38,113 +38,12 @@
 #include "i915_sysfs.h"
 #include "intel_pm.h"
 
-static inline struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
+struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
 {
 	struct drm_minor *minor = dev_get_drvdata(kdev);
 	return to_i915(minor->dev);
 }
 
-#ifdef CONFIG_PM
-static u32 calc_residency(struct drm_i915_private *dev_priv,
-			  i915_reg_t reg)
-{
-	intel_wakeref_t wakeref;
-	u64 res = 0;
-
-	with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref)
-		res = intel_rc6_residency_us(&to_gt(dev_priv)->rc6, reg);
-
-	return DIV_ROUND_CLOSEST_ULL(res, 1000);
-}
-
-static ssize_t rc6_enable_show(struct device *kdev,
-			       struct device_attribute *attr, char *buf)
-{
-	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	unsigned int mask;
-
-	mask = 0;
-	if (HAS_RC6(dev_priv))
-		mask |= BIT(0);
-	if (HAS_RC6p(dev_priv))
-		mask |= BIT(1);
-	if (HAS_RC6pp(dev_priv))
-		mask |= BIT(2);
-
-	return sysfs_emit(buf, "%x\n", mask);
-}
-
-static ssize_t rc6_residency_ms_show(struct device *kdev,
-				     struct device_attribute *attr, char *buf)
-{
-	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	u32 rc6_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6);
-	return sysfs_emit(buf, "%u\n", rc6_residency);
-}
-
-static ssize_t rc6p_residency_ms_show(struct device *kdev,
-				      struct device_attribute *attr, char *buf)
-{
-	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	u32 rc6p_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6p);
-	return sysfs_emit(buf, "%u\n", rc6p_residency);
-}
-
-static ssize_t rc6pp_residency_ms_show(struct device *kdev,
-				       struct device_attribute *attr, char *buf)
-{
-	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	u32 rc6pp_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6pp);
-	return sysfs_emit(buf, "%u\n", rc6pp_residency);
-}
-
-static ssize_t media_rc6_residency_ms_show(struct device *kdev,
-					   struct device_attribute *attr, char *buf)
-{
-	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	u32 rc6_residency = calc_residency(dev_priv, VLV_GT_MEDIA_RC6);
-	return sysfs_emit(buf, "%u\n", rc6_residency);
-}
-
-static DEVICE_ATTR_RO(rc6_enable);
-static DEVICE_ATTR_RO(rc6_residency_ms);
-static DEVICE_ATTR_RO(rc6p_residency_ms);
-static DEVICE_ATTR_RO(rc6pp_residency_ms);
-static DEVICE_ATTR_RO(media_rc6_residency_ms);
-
-static struct attribute *rc6_attrs[] = {
-	&dev_attr_rc6_enable.attr,
-	&dev_attr_rc6_residency_ms.attr,
-	NULL
-};
-
-static const struct attribute_group rc6_attr_group = {
-	.name = power_group_name,
-	.attrs =  rc6_attrs
-};
-
-static struct attribute *rc6p_attrs[] = {
-	&dev_attr_rc6p_residency_ms.attr,
-	&dev_attr_rc6pp_residency_ms.attr,
-	NULL
-};
-
-static const struct attribute_group rc6p_attr_group = {
-	.name = power_group_name,
-	.attrs =  rc6p_attrs
-};
-
-static struct attribute *media_rc6_attrs[] = {
-	&dev_attr_media_rc6_residency_ms.attr,
-	NULL
-};
-
-static const struct attribute_group media_rc6_attr_group = {
-	.name = power_group_name,
-	.attrs =  media_rc6_attrs
-};
-#endif
-
 static int l3_access_valid(struct drm_i915_private *i915, loff_t offset)
 {
 	if (!HAS_L3_DPF(i915))
@@ -256,171 +155,6 @@ static const struct bin_attribute dpf_attrs_1 = {
 	.private = (void *)1
 };
 
-static ssize_t gt_act_freq_mhz_show(struct device *kdev,
-				    struct device_attribute *attr, char *buf)
-{
-	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
-	struct intel_rps *rps = &to_gt(i915)->rps;
-
-	return sysfs_emit(buf, "%d\n", intel_rps_read_actual_frequency(rps));
-}
-
-static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
-				    struct device_attribute *attr, char *buf)
-{
-	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
-	struct intel_rps *rps = &to_gt(i915)->rps;
-
-	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)
-{
-	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
-	struct intel_rps *rps = &to_gt(i915)->rps;
-
-	return sysfs_emit(buf, "%d\n", intel_rps_get_boost_frequency(rps));
-}
-
-static ssize_t gt_boost_freq_mhz_store(struct device *kdev,
-				       struct device_attribute *attr,
-				       const char *buf, size_t count)
-{
-	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	struct intel_rps *rps = &to_gt(dev_priv)->rps;
-	ssize_t ret;
-	u32 val;
-
-	ret = kstrtou32(buf, 0, &val);
-	if (ret)
-		return ret;
-
-	ret = intel_rps_set_boost_frequency(rps, val);
-
-	return ret ?: count;
-}
-
-static ssize_t vlv_rpe_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 = &to_gt(dev_priv)->rps;
-
-	return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->efficient_freq));
-}
-
-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_gt *gt = to_gt(dev_priv);
-	struct intel_rps *rps = &gt->rps;
-
-	return sysfs_emit(buf, "%d\n", intel_rps_get_max_frequency(rps));
-}
-
-static ssize_t gt_max_freq_mhz_store(struct device *kdev,
-				     struct device_attribute *attr,
-				     const char *buf, size_t count)
-{
-	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-	struct intel_gt *gt = to_gt(dev_priv);
-	struct intel_rps *rps = &gt->rps;
-	ssize_t ret;
-	u32 val;
-
-	ret = kstrtou32(buf, 0, &val);
-	if (ret)
-		return ret;
-
-	ret = intel_rps_set_max_frequency(rps, val);
-
-	return ret ?: count;
-}
-
-static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
-{
-	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
-	struct intel_gt *gt = to_gt(i915);
-	struct intel_rps *rps = &gt->rps;
-
-	return sysfs_emit(buf, "%d\n", intel_rps_get_min_frequency(rps));
-}
-
-static ssize_t gt_min_freq_mhz_store(struct device *kdev,
-				     struct device_attribute *attr,
-				     const char *buf, size_t count)
-{
-	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
-	struct intel_rps *rps = &to_gt(i915)->rps;
-	ssize_t ret;
-	u32 val;
-
-	ret = kstrtou32(buf, 0, &val);
-	if (ret)
-		return ret;
-
-	ret = intel_rps_set_min_frequency(rps, val);
-
-	return ret ?: count;
-}
-
-static DEVICE_ATTR_RO(gt_act_freq_mhz);
-static DEVICE_ATTR_RO(gt_cur_freq_mhz);
-static DEVICE_ATTR_RW(gt_boost_freq_mhz);
-static DEVICE_ATTR_RW(gt_max_freq_mhz);
-static DEVICE_ATTR_RW(gt_min_freq_mhz);
-
-static DEVICE_ATTR_RO(vlv_rpe_freq_mhz);
-
-static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf);
-static DEVICE_ATTR(gt_RP0_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
-static DEVICE_ATTR(gt_RP1_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
-static DEVICE_ATTR(gt_RPn_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
-
-/* For now we have a static number of RP states */
-static ssize_t gt_rp_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 = &to_gt(dev_priv)->rps;
-	u32 val;
-
-	if (attr == &dev_attr_gt_RP0_freq_mhz)
-		val = intel_rps_get_rp0_frequency(rps);
-	else if (attr == &dev_attr_gt_RP1_freq_mhz)
-		val = intel_rps_get_rp1_frequency(rps);
-	else if (attr == &dev_attr_gt_RPn_freq_mhz)
-		val = intel_rps_get_rpn_frequency(rps);
-	else
-		BUG();
-
-	return sysfs_emit(buf, "%d\n", val);
-}
-
-static const struct attribute * const gen6_attrs[] = {
-	&dev_attr_gt_act_freq_mhz.attr,
-	&dev_attr_gt_cur_freq_mhz.attr,
-	&dev_attr_gt_boost_freq_mhz.attr,
-	&dev_attr_gt_max_freq_mhz.attr,
-	&dev_attr_gt_min_freq_mhz.attr,
-	&dev_attr_gt_RP0_freq_mhz.attr,
-	&dev_attr_gt_RP1_freq_mhz.attr,
-	&dev_attr_gt_RPn_freq_mhz.attr,
-	NULL,
-};
-
-static const struct attribute * const vlv_attrs[] = {
-	&dev_attr_gt_act_freq_mhz.attr,
-	&dev_attr_gt_cur_freq_mhz.attr,
-	&dev_attr_gt_boost_freq_mhz.attr,
-	&dev_attr_gt_max_freq_mhz.attr,
-	&dev_attr_gt_min_freq_mhz.attr,
-	&dev_attr_gt_RP0_freq_mhz.attr,
-	&dev_attr_gt_RP1_freq_mhz.attr,
-	&dev_attr_gt_RPn_freq_mhz.attr,
-	&dev_attr_vlv_rpe_freq_mhz.attr,
-	NULL,
-};
-
 #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
 
 static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
@@ -486,34 +220,16 @@ static void i915_setup_error_capture(struct device *kdev) {}
 static void i915_teardown_error_capture(struct device *kdev) {}
 #endif
 
+static struct kobject *i915_setup_gt_sysfs(struct kobject *parent)
+{
+	return kobject_create_and_add("gt", parent);
+}
+
 void i915_setup_sysfs(struct drm_i915_private *dev_priv)
 {
 	struct device *kdev = dev_priv->drm.primary->kdev;
 	int ret;
 
-#ifdef CONFIG_PM
-	if (HAS_RC6(dev_priv)) {
-		ret = sysfs_merge_group(&kdev->kobj,
-					&rc6_attr_group);
-		if (ret)
-			drm_err(&dev_priv->drm,
-				"RC6 residency sysfs setup failed\n");
-	}
-	if (HAS_RC6p(dev_priv)) {
-		ret = sysfs_merge_group(&kdev->kobj,
-					&rc6p_attr_group);
-		if (ret)
-			drm_err(&dev_priv->drm,
-				"RC6p residency sysfs setup failed\n");
-	}
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-		ret = sysfs_merge_group(&kdev->kobj,
-					&media_rc6_attr_group);
-		if (ret)
-			drm_err(&dev_priv->drm,
-				"Media RC6 residency sysfs setup failed\n");
-	}
-#endif
 	if (HAS_L3_DPF(dev_priv)) {
 		ret = device_create_bin_file(kdev, &dpf_attrs);
 		if (ret)
@@ -529,13 +245,10 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv)
 		}
 	}
 
-	ret = 0;
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		ret = sysfs_create_files(&kdev->kobj, vlv_attrs);
-	else if (GRAPHICS_VER(dev_priv) >= 6)
-		ret = sysfs_create_files(&kdev->kobj, gen6_attrs);
-	if (ret)
-		drm_err(&dev_priv->drm, "RPS sysfs setup failed\n");
+	dev_priv->sysfs_gt = i915_setup_gt_sysfs(&kdev->kobj);
+	if (!dev_priv->sysfs_gt)
+		drm_err(&dev_priv->drm,
+			"failed to register GT sysfs directory\n");
 
 	i915_setup_error_capture(kdev);
 
@@ -548,14 +261,6 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv)
 
 	i915_teardown_error_capture(kdev);
 
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		sysfs_remove_files(&kdev->kobj, vlv_attrs);
-	else
-		sysfs_remove_files(&kdev->kobj, gen6_attrs);
 	device_remove_bin_file(kdev,  &dpf_attrs_1);
 	device_remove_bin_file(kdev,  &dpf_attrs);
-#ifdef CONFIG_PM
-	sysfs_unmerge_group(&kdev->kobj, &rc6_attr_group);
-	sysfs_unmerge_group(&kdev->kobj, &rc6p_attr_group);
-#endif
 }
diff --git a/drivers/gpu/drm/i915/i915_sysfs.h b/drivers/gpu/drm/i915/i915_sysfs.h
index 41afd4366416..243a17741e3f 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.h
+++ b/drivers/gpu/drm/i915/i915_sysfs.h
@@ -6,8 +6,11 @@
 #ifndef __I915_SYSFS_H__
 #define __I915_SYSFS_H__
 
+struct device;
 struct drm_i915_private;
 
+struct drm_i915_private *kdev_minor_to_i915(struct device *kdev);
+
 void i915_setup_sysfs(struct drm_i915_private *i915);
 void i915_teardown_sysfs(struct drm_i915_private *i915);
 
-- 
2.34.1


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

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for Introduce multitile support
  2022-01-17 15:09 ` [Intel-gfx] " Andi Shyti
                   ` (2 preceding siblings ...)
  (?)
@ 2022-01-17 15:38 ` Patchwork
  -1 siblings, 0 replies; 17+ messages in thread
From: Patchwork @ 2022-01-17 15:38 UTC (permalink / raw)
  To: Andi Shyti; +Cc: intel-gfx

== Series Details ==

Series: Introduce multitile support
URL   : https://patchwork.freedesktop.org/series/98950/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
28afa8633a19 drm/i915: Prepare for multiple GTs
-:255: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'id__' - possible side-effects?
#255: FILE: drivers/gpu/drm/i915/gt/intel_gt.h:91:
+#define for_each_gt(gt__, i915__, id__) \
+	for ((id__) = 0; \
+	     (id__) < I915_MAX_GT; \
+	     (id__)++) \
+		for_each_if(((gt__) = (i915__)->gt[(id__)]))

total: 0 errors, 0 warnings, 1 checks, 436 lines checked
9028d350f206 drm/i915/gt: make a gt sysfs group and move power management files
-:112: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#112: 
new file mode 100644

-:592: CHECK:MACRO_ARG_REUSE: Macro argument reuse '_mode' - possible side-effects?
#592: FILE: drivers/gpu/drm/i915/gt/sysfs_gt_pm.c:294:
+#define INTEL_GT_RPS_SYSFS_ATTR(_name, _mode, _show, _store) \
+	struct device_attribute dev_attr_gt_##_name = __ATTR(gt_##_name, _mode, _show, _store); \
+	struct device_attribute dev_attr_rps_##_name = __ATTR(rps_##_name, _mode, _show, _store)

-:592: CHECK:MACRO_ARG_REUSE: Macro argument reuse '_show' - possible side-effects?
#592: FILE: drivers/gpu/drm/i915/gt/sysfs_gt_pm.c:294:
+#define INTEL_GT_RPS_SYSFS_ATTR(_name, _mode, _show, _store) \
+	struct device_attribute dev_attr_gt_##_name = __ATTR(gt_##_name, _mode, _show, _store); \
+	struct device_attribute dev_attr_rps_##_name = __ATTR(rps_##_name, _mode, _show, _store)

-:592: CHECK:MACRO_ARG_REUSE: Macro argument reuse '_store' - possible side-effects?
#592: FILE: drivers/gpu/drm/i915/gt/sysfs_gt_pm.c:294:
+#define INTEL_GT_RPS_SYSFS_ATTR(_name, _mode, _show, _store) \
+	struct device_attribute dev_attr_gt_##_name = __ATTR(gt_##_name, _mode, _show, _store); \
+	struct device_attribute dev_attr_rps_##_name = __ATTR(rps_##_name, _mode, _show, _store)

-:615: CHECK:CAMELCASE: Avoid CamelCase: <RPn_freq_mhz>
#615: FILE: drivers/gpu/drm/i915/gt/sysfs_gt_pm.c:317:
+static INTEL_GT_RPS_SYSFS_ATTR(RPn_freq_mhz, 0444, rps_rp_mhz_show, NULL);

-:625: CHECK:CAMELCASE: Avoid CamelCase: <dev_attr_##s##_RPn_freq_mhz>
#625: FILE: drivers/gpu/drm/i915/gt/sysfs_gt_pm.c:327:
+		&dev_attr_##s##_RPn_freq_mhz.attr, \

-:644: WARNING:SUSPECT_CODE_INDENT: suspect code indent for conditional statements (8, 19)
#644: FILE: drivers/gpu/drm/i915/gt/sysfs_gt_pm.c:346:
+	} else if (attr == &dev_attr_gt_RP1_freq_mhz ||
[...]
+		   val = intel_rps_get_rp1_frequency(rps);

-:647: WARNING:SUSPECT_CODE_INDENT: suspect code indent for conditional statements (8, 19)
#647: FILE: drivers/gpu/drm/i915/gt/sysfs_gt_pm.c:349:
+	} else if (attr == &dev_attr_gt_RPn_freq_mhz ||
[...]
+		   val = intel_rps_get_rpn_frequency(rps);

-:647: CHECK:CAMELCASE: Avoid CamelCase: <dev_attr_gt_RPn_freq_mhz>
#647: FILE: drivers/gpu/drm/i915/gt/sysfs_gt_pm.c:349:
+	} else if (attr == &dev_attr_gt_RPn_freq_mhz ||

-:648: CHECK:CAMELCASE: Avoid CamelCase: <dev_attr_rps_RPn_freq_mhz>
#648: FILE: drivers/gpu/drm/i915/gt/sysfs_gt_pm.c:350:
+		   attr == &dev_attr_rps_RPn_freq_mhz) {

total: 0 errors, 3 warnings, 7 checks, 984 lines checked



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

* [Intel-gfx] ✗ Fi.CI.SPARSE: warning for Introduce multitile support
  2022-01-17 15:09 ` [Intel-gfx] " Andi Shyti
                   ` (3 preceding siblings ...)
  (?)
@ 2022-01-17 15:39 ` Patchwork
  -1 siblings, 0 replies; 17+ messages in thread
From: Patchwork @ 2022-01-17 15:39 UTC (permalink / raw)
  To: Andi Shyti; +Cc: intel-gfx

== Series Details ==

Series: Introduce multitile support
URL   : https://patchwork.freedesktop.org/series/98950/
State : warning

== Summary ==

$ dim sparse --fast origin/drm-tip
Sparse version: v0.6.2
Fast mode used, each commit won't be checked separately.



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

* Re: [Intel-gfx] [PATCH v3 2/2] drm/i915/gt: make a gt sysfs group and move power management files
  2022-01-17 15:09   ` [Intel-gfx] " Andi Shyti
  (?)
@ 2022-01-17 16:02   ` Tvrtko Ursulin
  2022-01-17 17:16       ` Andi Shyti
  2022-01-19  7:19       ` Joonas Lahtinen
  -1 siblings, 2 replies; 17+ messages in thread
From: Tvrtko Ursulin @ 2022-01-17 16:02 UTC (permalink / raw)
  To: Andi Shyti, Intel GFX, DRI Devel
  Cc: Lucas De Marchi, Abdiel Janulgue, Matthew Auld


On 17/01/2022 15:09, Andi Shyti wrote:
> The GT has its own properties and in sysfs they should be grouped
> in the 'gt/' directory.
> 
> Create a 'gt/' directory in sysfs which will contain gt0...gtN
> directories related to each tile configured in the GPU. Move the
> power management files inside those directories.
> 
> The previous power management files are kept in their original
> root directory to avoid breaking the ABI. They point to the tile
> '0' and a warning message is printed whenever accessed to. The
> deprecated interface needs for the CONFIG_SYSFS_DEPRECATED_V2
> flag in order to be generated.

CONFIG_SYSFS_DEPRECATED_V2 idea was abandoned, no? This patch at least 
does not appear to contain it so please update the commit message to 
reflect current state.

Adding Joonas to help address the question of how strict are userspace 
requirements for sysfs additions. Personally sysadmin use sounds fine to 
me, although it needs to be mentioned/documented as Matt requested, but 
I fear it may not be enough to upstream. Is Level0 at the stage where we 
can upstream for it I am also not sure.

While I am here I also left some nits below (not full review).

> 
> The new sysfs structure will have a similar layout for the 4 tile
> case:
> 
> /sys/.../card0
>           ├── gt
>           │   ├── gt0
>           │   │   ├── id
>           │   │   ├── rc6_enable
>           │   │   ├── rc6_residency_ms
>           │   │   ├── rps_act_freq_mhz
>           │   │   ├── rps_boost_freq_mhz
>           │   │   ├── rps_cur_freq_mhz
>           │   │   ├── rps_max_freq_mhz
>           │   │   ├── rps_min_freq_mhz
>           │   │   ├── rps_RP0_freq_mhz
>           │   │   ├── rps_RP1_freq_mhz
>           │   │   └── rps_RPn_freq_mhz
> 	 .   .
> 	 .   .
> 	 .   .
>           │   └── gt3
>           │       ├── id
>           │       ├── rc6_enable
>           │       ├── rc6_residency_ms
>           │       ├── rps_act_freq_mhz
>           │       ├── rps_boost_freq_mhz
>           │       ├── rps_cur_freq_mhz
>           │       ├── rps_max_freq_mhz
>           │       ├── rps_min_freq_mhz
>           │       ├── rps_RP0_freq_mhz
>           │       ├── rps_RP1_freq_mhz
>           │       └── rps_RPn_freq_mhz
>           ├── gt_act_freq_mhz   -+
>           ├── gt_boost_freq_mhz  |
>           ├── gt_cur_freq_mhz    |    Original interface
>           ├── gt_max_freq_mhz    +─-> kept as existing ABI;
>           ├── gt_min_freq_mhz    |    it points to gt0/
>           ├── gt_RP0_freq_mhz    |
>           └── gt_RP1_freq_mhz    |
>           └── gt_RPn_freq_mhz   -+
> 
> As soon as multitile platforms will start being supported, this
> interface will allow to control the power (either manually or
> with tools) on each tile, instead of affecting only tile 0 and
> getting incomplete results.
> 
> Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
> Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
> Cc: Matt Roper <matthew.d.roper@intel.com>
> Cc: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Reviewed-by: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
> ---
>   drivers/gpu/drm/i915/Makefile         |   4 +-
>   drivers/gpu/drm/i915/gt/intel_gt.c    |   2 +
>   drivers/gpu/drm/i915/gt/sysfs_gt.c    | 126 +++++++++
>   drivers/gpu/drm/i915/gt/sysfs_gt.h    |  44 +++
>   drivers/gpu/drm/i915/gt/sysfs_gt_pm.c | 393 ++++++++++++++++++++++++++
>   drivers/gpu/drm/i915/gt/sysfs_gt_pm.h |  16 ++
>   drivers/gpu/drm/i915/i915_drv.h       |   2 +
>   drivers/gpu/drm/i915/i915_reg.h       |   1 +
>   drivers/gpu/drm/i915/i915_sysfs.c     | 315 +--------------------
>   drivers/gpu/drm/i915/i915_sysfs.h     |   3 +
>   10 files changed, 600 insertions(+), 306 deletions(-)
>   create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt.c
>   create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt.h
>   create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
>   create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt_pm.h
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index aa86ac33effc..5fd203c626fc 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -121,7 +121,9 @@ gt-y += \
>   	gt/intel_timeline.o \
>   	gt/intel_workarounds.o \
>   	gt/shmem_utils.o \
> -	gt/sysfs_engines.o
> +	gt/sysfs_engines.o \
> +	gt/sysfs_gt.o \
> +	gt/sysfs_gt_pm.o
>   # autogenerated null render state
>   gt-y += \
>   	gt/gen6_renderstate.o \
> diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
> index 17927da9e23e..2584c51c1c14 100644
> --- a/drivers/gpu/drm/i915/gt/intel_gt.c
> +++ b/drivers/gpu/drm/i915/gt/intel_gt.c
> @@ -25,6 +25,7 @@
>   #include "intel_rps.h"
>   #include "intel_uncore.h"
>   #include "shmem_utils.h"
> +#include "sysfs_gt.h"
>   #include "pxp/intel_pxp.h"
>   
>   static void
> @@ -453,6 +454,7 @@ void intel_gt_driver_register(struct intel_gt *gt)
>   	intel_rps_driver_register(&gt->rps);
>   
>   	intel_gt_debugfs_register(gt);
> +	intel_gt_sysfs_register(gt);
>   }
>   
>   static int intel_gt_init_scratch(struct intel_gt *gt, unsigned int size)
> diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt.c b/drivers/gpu/drm/i915/gt/sysfs_gt.c
> new file mode 100644
> index 000000000000..46cf033a53ec
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gt/sysfs_gt.c
> @@ -0,0 +1,126 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2020 Intel Corporation
> + */
> +
> +#include <drm/drm_device.h>
> +#include <linux/device.h>
> +#include <linux/kobject.h>
> +#include <linux/printk.h>
> +#include <linux/sysfs.h>
> +
> +#include "i915_drv.h"
> +#include "i915_sysfs.h"
> +#include "intel_gt.h"
> +#include "intel_gt_types.h"
> +#include "intel_rc6.h"
> +
> +#include "sysfs_gt.h"
> +#include "sysfs_gt_pm.h"
> +
> +struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
> +					    const char *name)
> +{
> +	struct kobject *kobj = &dev->kobj;
> +
> +	/*
> +	 * We are interested at knowing from where the interface
> +	 * has been called, whether it's called from gt/ or from
> +	 * the parent directory.
> +	 * From the interface position it depends also the value of
> +	 * the private data.
> +	 * If the interface is called from gt/ then private data is
> +	 * of the "struct intel_gt *" type, otherwise it's * a
> +	 * "struct drm_i915_private *" type.
> +	 */
> +	if (!is_object_gt(kobj)) {
> +		struct drm_i915_private *i915 = kdev_minor_to_i915(dev);
> +
> +		pr_devel_ratelimited(DEPRECATED
> +			"%s (pid %d) is trying to access deprecated %s "
> +			"sysfs control, please use gt/gt<n>/%s instead\n",

Maybe reword "is trying to access" to "is accesing" to remove any doubt 
whether something is failing or not?

> +			current->comm, task_pid_nr(current), name, name);
> +		return to_gt(i915);
> +	}
> +
> +	return kobj_to_gt(kobj);
> +}
> +
> +static struct kobject *gt_get_parent_obj(struct intel_gt *gt)
> +{
> +	return &gt->i915->drm.primary->kdev->kobj;
> +}
> +
> +static ssize_t id_show(struct device *dev,
> +		       struct device_attribute *attr,
> +		       char *buf)
> +{
> +	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> +
> +	return sysfs_emit(buf, "%u\n", gt->info.id);
> +}
> +
> +static DEVICE_ATTR_RO(id);
> +
> +static void kobj_gt_release(struct kobject *kobj)
> +{
> +	kfree(kobj);
> +}
> +
> +static struct kobj_type kobj_gt_type = {
> +	.release = kobj_gt_release,
> +	.sysfs_ops = &kobj_sysfs_ops
> +};
> +
> +struct kobject *
> +intel_gt_create_kobj(struct intel_gt *gt, struct kobject *dir, const char *name)
> +{
> +	struct kobj_gt *kg;
> +
> +	kg = kzalloc(sizeof(*kg), GFP_KERNEL);
> +	if (!kg)
> +		return NULL;
> +
> +	kobject_init(&kg->base, &kobj_gt_type);
> +	kg->gt = gt;
> +
> +	/* xfer ownership to sysfs tree */
> +	if (kobject_add(&kg->base, dir, "%s", name)) {
> +		kobject_put(&kg->base);
> +		return NULL;
> +	}
> +
> +	return &kg->base; /* borrowed ref */
> +}
> +
> +void intel_gt_sysfs_register(struct intel_gt *gt)
> +{
> +	struct kobject *dir;
> +	char name[80];
> +
> +	/*
> +	 * We need to make things right with the
> +	 * ABI compatibility. The files were originally
> +	 * generated under the parent directory.
> +	 *
> +	 * We generate the files only for gt 0
> +	 * to avoid duplicates.
> +	 */
> +	if (!gt->info.id)
> +		intel_gt_sysfs_pm_init(gt, gt_get_parent_obj(gt));
> +
> +	snprintf(name, sizeof(name), "gt%d", gt->info.id);
> +
> +	dir = intel_gt_create_kobj(gt, gt->i915->sysfs_gt, name);
> +	if (!dir) {
> +		drm_err(&gt->i915->drm,
> +			"failed to initialize %s sysfs root\n", name);
> +		return;
> +	}
> +
> +	if (sysfs_create_file(dir, &dev_attr_id.attr))
> +		drm_err(&gt->i915->drm,
> +			"failed to create sysfs %s info files\n", name);

These drm_err could maybe be warn or notice, to reflect the fact driver 
is most likely completely functional? But only maybe since I haven't 
checked what we do for other sysfs failures. If rest are drm_err then I 
guess consistency trumps it.

> +
> +	intel_gt_sysfs_pm_init(gt, dir);
> +}
> diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt.h b/drivers/gpu/drm/i915/gt/sysfs_gt.h
> new file mode 100644
> index 000000000000..cd80a14bb14d
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gt/sysfs_gt.h
> @@ -0,0 +1,44 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2020 Intel Corporation
> + */
> +
> +#ifndef __SYSFS_GT_H__
> +#define __SYSFS_GT_H__
> +
> +#include <linux/ctype.h>
> +#include <linux/kobject.h>
> +
> +#include "i915_gem.h" /* GEM_BUG_ON() */
> +
> +struct intel_gt;
> +
> +struct kobj_gt {
> +	struct kobject base;
> +	struct intel_gt *gt;
> +};
> +
> +static inline bool is_object_gt(struct kobject *kobj)
> +{
> +	bool b = !strncmp(kobj->name, "gt", 2);
> +
> +	GEM_BUG_ON(b && !isdigit(kobj->name[2]));

1)
Not sure what is the point of this GEM_BUG_ON? Checking strncmp works 
feels like an overkill.

2)
With the recent trend of "static inline considered harmful" perhaps 
consider moving it out of line.

> +
> +	return b;
> +}
> +
> +struct kobject *
> +intel_gt_create_kobj(struct intel_gt *gt,
> +		     struct kobject *dir,
> +		     const char *name);
> +
> +static inline struct intel_gt *kobj_to_gt(struct kobject *kobj)
> +{
> +	return container_of(kobj, struct kobj_gt, base)->gt;
> +}
> +
> +void intel_gt_sysfs_register(struct intel_gt *gt);
> +struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
> +					    const char *name);
> +
> +#endif /* SYSFS_GT_H */
> diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt_pm.c b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
> new file mode 100644
> index 000000000000..6f4424be42d1
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
> @@ -0,0 +1,393 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2020 Intel Corporation
> + */
> +
> +#include <drm/drm_device.h>
> +#include <linux/sysfs.h>
> +#include <linux/printk.h>
> +
> +#include "i915_drv.h"
> +#include "intel_gt.h"
> +#include "intel_rc6.h"
> +#include "intel_rps.h"
> +#include "sysfs_gt.h"
> +#include "sysfs_gt_pm.h"
> +
> +#ifdef CONFIG_PM
> +static u32 get_residency(struct intel_gt *gt, i915_reg_t reg)
> +{
> +	intel_wakeref_t wakeref;
> +	u64 res = 0;
> +
> +	with_intel_runtime_pm(gt->uncore->rpm, wakeref)
> +		res = intel_rc6_residency_us(&gt->rc6, reg);
> +
> +	return DIV_ROUND_CLOSEST_ULL(res, 1000);
> +}
> +
> +static ssize_t rc6_enable_show(struct device *dev,
> +			       struct device_attribute *attr,
> +			       char *buff)
> +{
> +	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> +	u8 mask = 0;
> +
> +	if (HAS_RC6(gt->i915))
> +		mask |= BIT(0);
> +	if (HAS_RC6p(gt->i915))
> +		mask |= BIT(1);
> +	if (HAS_RC6pp(gt->i915))
> +		mask |= BIT(2);
> +
> +	return scnprintf(buff, PAGE_SIZE, "%x\n", mask);
> +}
> +
> +static ssize_t rc6_residency_ms_show(struct device *dev,
> +				     struct device_attribute *attr,
> +				     char *buff)
> +{
> +	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> +	u32 rc6_residency = get_residency(gt, GEN6_GT_GFX_RC6);
> +
> +	return scnprintf(buff, PAGE_SIZE, "%u\n", rc6_residency);
> +}
> +
> +static ssize_t rc6p_residency_ms_show(struct device *dev,
> +				      struct device_attribute *attr,
> +				      char *buff)
> +{
> +	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> +	u32 rc6p_residency = get_residency(gt, GEN6_GT_GFX_RC6p);
> +
> +	return scnprintf(buff, PAGE_SIZE, "%u\n", rc6p_residency);
> +}
> +
> +static ssize_t rc6pp_residency_ms_show(struct device *dev,
> +				       struct device_attribute *attr,
> +				       char *buff)
> +{
> +	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> +	u32 rc6pp_residency = get_residency(gt, GEN6_GT_GFX_RC6pp);
> +
> +	return scnprintf(buff, PAGE_SIZE, "%u\n", rc6pp_residency);
> +}
> +
> +static ssize_t media_rc6_residency_ms_show(struct device *dev,
> +					   struct device_attribute *attr,
> +					   char *buff)
> +{
> +	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> +	u32 rc6_residency = get_residency(gt, VLV_GT_MEDIA_RC6);
> +
> +	return scnprintf(buff, PAGE_SIZE, "%u\n", rc6_residency);
> +}
> +
> +static DEVICE_ATTR_RO(rc6_enable);
> +static DEVICE_ATTR_RO(rc6_residency_ms);
> +static DEVICE_ATTR_RO(rc6p_residency_ms);
> +static DEVICE_ATTR_RO(rc6pp_residency_ms);
> +static DEVICE_ATTR_RO(media_rc6_residency_ms);
> +
> +static struct attribute *rc6_attrs[] = {
> +	&dev_attr_rc6_enable.attr,
> +	&dev_attr_rc6_residency_ms.attr,
> +	NULL
> +};
> +
> +static struct attribute *rc6p_attrs[] = {
> +	&dev_attr_rc6p_residency_ms.attr,
> +	&dev_attr_rc6pp_residency_ms.attr,
> +	NULL
> +};
> +
> +static struct attribute *media_rc6_attrs[] = {
> +	&dev_attr_media_rc6_residency_ms.attr,
> +	NULL
> +};
> +
> +static const struct attribute_group rc6_attr_group[] = {
> +	{ .name = power_group_name, .attrs = rc6_attrs },
> +	{ .attrs = rc6_attrs }
> +};
> +
> +static const struct attribute_group rc6p_attr_group[] = {
> +	{ .name = power_group_name, .attrs = rc6p_attrs },
> +	{ .attrs = rc6p_attrs }
> +};
> +
> +static const struct attribute_group media_rc6_attr_group[] = {
> +	{ .name = power_group_name, .attrs = media_rc6_attrs },
> +	{ .attrs = media_rc6_attrs }
> +};
> +
> +static int __intel_gt_sysfs_create_group(struct kobject *kobj,
> +					 const struct attribute_group *grp)
> +{
> +	int i = is_object_gt(kobj);

Is_object_gt returns a bool so can I be pedantic? :) Maybe just omit the 
local and solve it like that.

> +
> +	return i ? sysfs_create_group(kobj, &grp[i]) :
> +		   sysfs_merge_group(kobj, &grp[i]);
> +}
> +
> +static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj)
> +{
> +	int ret;
> +
> +	if (!HAS_RC6(gt->i915))
> +		return;
> +
> +	ret = __intel_gt_sysfs_create_group(kobj, rc6_attr_group);
> +	if (ret)
> +		drm_err(&gt->i915->drm,
> +			"failed to create gt%u RC6 sysfs files\n", gt->info.id);
> +
> +	if (HAS_RC6p(gt->i915)) {
> +		ret = __intel_gt_sysfs_create_group(kobj, rc6p_attr_group);
> +		if (ret)
> +			drm_err(&gt->i915->drm,
> +				"failed to create gt%u RC6p sysfs files\n",
> +				gt->info.id);
> +	}
> +
> +	if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915)) {
> +		ret = __intel_gt_sysfs_create_group(kobj, media_rc6_attr_group);
> +		if (ret)
> +			drm_err(&gt->i915->drm,
> +				"failed to create media %u RC6 sysfs files\n",
> +				gt->info.id);
> +	}
> +}
> +#else
> +static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj)
> +{
> +}
> +#endif /* CONFIG_PM */
> +
> +static ssize_t act_freq_mhz_show(struct device *dev,
> +				 struct device_attribute *attr, char *buff)
> +{
> +	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> +
> +	return scnprintf(buff, PAGE_SIZE, "%d\n",
> +			intel_rps_read_actual_frequency(&gt->rps));
> +}
> +
> +static ssize_t cur_freq_mhz_show(struct device *dev,
> +				 struct device_attribute *attr, char *buff)
> +{
> +	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> +	struct intel_rps *rps = &gt->rps;
> +
> +	return scnprintf(buff, PAGE_SIZE, "%d\n",
> +			 intel_rps_get_requested_frequency(rps));
> +}
> +
> +static ssize_t boost_freq_mhz_show(struct device *dev,
> +				   struct device_attribute *attr,
> +				   char *buff)
> +{
> +	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> +	struct intel_rps *rps = &gt->rps;
> +
> +	return scnprintf(buff, PAGE_SIZE, "%d\n",
> +			 intel_rps_get_boost_frequency(rps));
> +}
> +
> +static ssize_t boost_freq_mhz_store(struct device *dev,
> +				    struct device_attribute *attr,
> +				    const char *buff, size_t count)
> +{
> +	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> +	struct intel_rps *rps = &gt->rps;
> +	bool boost = false;
> +	ssize_t ret;
> +	u32 val;
> +
> +	ret = kstrtou32(buff, 0, &val);
> +	if (ret)
> +		return ret;
> +
> +	/* Validate against (static) hardware limits */
> +	val = intel_freq_opcode(rps, val);
> +	if (val < rps->min_freq || val > rps->max_freq)
> +		return -EINVAL;
> +
> +	mutex_lock(&rps->lock);
> +	if (val != rps->boost_freq) {
> +		rps->boost_freq = val;
> +		boost = atomic_read(&rps->num_waiters);
> +	}
> +	mutex_unlock(&rps->lock);
> +	if (boost)
> +		schedule_work(&rps->work);
> +
> +	return count;
> +}
> +
> +static ssize_t vlv_rpe_freq_mhz_show(struct device *dev,
> +				     struct device_attribute *attr, char *buff)
> +{
> +	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> +	struct intel_rps *rps = &gt->rps;
> +
> +	return scnprintf(buff, PAGE_SIZE, "%d\n",
> +			intel_gpu_freq(rps, rps->efficient_freq));
> +}
> +
> +static ssize_t max_freq_mhz_show(struct device *dev,
> +				 struct device_attribute *attr,
> +				 char *buff)
> +{
> +	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> +	struct intel_rps *rps = &gt->rps;
> +
> +	return sysfs_emit(buff, "%d\n", intel_rps_get_max_frequency(rps));
> +}
> +
> +static ssize_t max_freq_mhz_store(struct device *dev,
> +				  struct device_attribute *attr,
> +				  const char *buff, size_t count)
> +{
> +	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> +	struct intel_rps *rps = &gt->rps;
> +	ssize_t ret;
> +	u32 val;
> +
> +	ret = kstrtou32(buff, 0, &val);
> +	if (ret)
> +		return ret;
> +
> +	ret = intel_rps_set_max_frequency(rps, val);
> +
> +	return ret ?: count;
> +}
> +
> +static ssize_t min_freq_mhz_show(struct device *dev,
> +				 struct device_attribute *attr,
> +				 char *buff)
> +{
> +	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> +	struct intel_rps *rps = &gt->rps;
> +
> +	return sysfs_emit(buff, "%d\n", intel_rps_get_min_frequency(rps));
> +}
> +
> +static ssize_t min_freq_mhz_store(struct device *dev,
> +				  struct device_attribute *attr,
> +				  const char *buff, size_t count)
> +{
> +	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> +	struct intel_rps *rps = &gt->rps;
> +	ssize_t ret;
> +	u32 val;
> +
> +	ret = kstrtou32(buff, 0, &val);
> +	if (ret)
> +		return ret;
> +
> +	ret = intel_rps_set_min_frequency(rps, val);
> +
> +	return ret ?: count;
> +}
> +
> +#define INTEL_GT_RPS_SYSFS_ATTR(_name, _mode, _show, _store) \
> +	struct device_attribute dev_attr_gt_##_name = __ATTR(gt_##_name, _mode, _show, _store); \
> +	struct device_attribute dev_attr_rps_##_name = __ATTR(rps_##_name, _mode, _show, _store)
> +
> +#define INTEL_GT_RPS_SYSFS_ATTR_RO(_name)				\
> +		INTEL_GT_RPS_SYSFS_ATTR(_name, 0444, _name##_show, NULL)
> +#define INTEL_GT_RPS_SYSFS_ATTR_RW(_name)				\
> +		INTEL_GT_RPS_SYSFS_ATTR(_name, 0644, _name##_show, _name##_store)
> +
> +static INTEL_GT_RPS_SYSFS_ATTR_RO(act_freq_mhz);
> +static INTEL_GT_RPS_SYSFS_ATTR_RO(cur_freq_mhz);
> +static INTEL_GT_RPS_SYSFS_ATTR_RW(boost_freq_mhz);
> +static INTEL_GT_RPS_SYSFS_ATTR_RW(max_freq_mhz);
> +static INTEL_GT_RPS_SYSFS_ATTR_RW(min_freq_mhz);
> +
> +static DEVICE_ATTR_RO(vlv_rpe_freq_mhz);
> +
> +static ssize_t rps_rp_mhz_show(struct device *dev,
> +			       struct device_attribute *attr,
> +			       char *buff);
> +
> +static INTEL_GT_RPS_SYSFS_ATTR(RP0_freq_mhz, 0444, rps_rp_mhz_show, NULL);
> +static INTEL_GT_RPS_SYSFS_ATTR(RP1_freq_mhz, 0444, rps_rp_mhz_show, NULL);
> +static INTEL_GT_RPS_SYSFS_ATTR(RPn_freq_mhz, 0444, rps_rp_mhz_show, NULL);
> +
> +#define GEN6_ATTR(s) { \
> +		&dev_attr_##s##_act_freq_mhz.attr, \
> +		&dev_attr_##s##_cur_freq_mhz.attr, \
> +		&dev_attr_##s##_boost_freq_mhz.attr, \
> +		&dev_attr_##s##_max_freq_mhz.attr, \
> +		&dev_attr_##s##_min_freq_mhz.attr, \
> +		&dev_attr_##s##_RP0_freq_mhz.attr, \
> +		&dev_attr_##s##_RP1_freq_mhz.attr, \
> +		&dev_attr_##s##_RPn_freq_mhz.attr, \
> +		NULL, \
> +	}
> +
> +#define GEN6_RPS_ATTR GEN6_ATTR(rps)
> +#define GEN6_GT_ATTR  GEN6_ATTR(gt)
> +
> +/* For now we have a static number of RP states */
> +static ssize_t rps_rp_mhz_show(struct device *dev,
> +			       struct device_attribute *attr,
> +			       char *buff)
> +{
> +	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> +	struct intel_rps *rps = &gt->rps;
> +	u32 val;
> +
> +	if (attr == &dev_attr_gt_RP0_freq_mhz ||
> +	    attr == &dev_attr_rps_RP0_freq_mhz) {
> +		val = intel_rps_get_rp0_frequency(rps);
> +	} else if (attr == &dev_attr_gt_RP1_freq_mhz ||
> +		   attr == &dev_attr_rps_RP1_freq_mhz) {
> +		   val = intel_rps_get_rp1_frequency(rps);
> +	} else if (attr == &dev_attr_gt_RPn_freq_mhz ||
> +		   attr == &dev_attr_rps_RPn_freq_mhz) {
> +		   val = intel_rps_get_rpn_frequency(rps);
> +	} else {
> +		GEM_WARN_ON(1);
> +		return -ENODEV;
> +	}
> +
> +	return scnprintf(buff, PAGE_SIZE, "%d\n", val);
> +}
> +
> +static const struct attribute * const gen6_rps_attrs[] = GEN6_RPS_ATTR;
> +static const struct attribute * const gen6_gt_attrs[]  = GEN6_GT_ATTR;
> +
> +static int intel_sysfs_rps_init(struct intel_gt *gt, struct kobject *kobj,
> +				const struct attribute * const *attrs)
> +{
> +	int ret;
> +
> +	if (GRAPHICS_VER(gt->i915) < 6)
> +		return 0;
> +
> +	ret = sysfs_create_files(kobj, attrs);
> +	if (ret)
> +		return ret;
> +
> +	if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915))
> +		ret = sysfs_create_file(kobj, &dev_attr_vlv_rpe_freq_mhz.attr);
> +
> +	return ret;
> +}
> +
> +void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj)
> +{
> +	int ret;
> +
> +	intel_sysfs_rc6_init(gt, kobj);
> +
> +	ret = is_object_gt(kobj) ?
> +	      intel_sysfs_rps_init(gt, kobj, gen6_rps_attrs) :
> +	      intel_sysfs_rps_init(gt, kobj, gen6_gt_attrs);
> +	if (ret)
> +		drm_err(&gt->i915->drm,
> +			"failed to create gt%u RPS sysfs files", gt->info.id);
> +}
> diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt_pm.h b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.h
> new file mode 100644
> index 000000000000..18c60d929e6d
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.h
> @@ -0,0 +1,16 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2020 Intel Corporation
> + */
> +
> +#ifndef __SYSFS_GT_PM_H__
> +#define __SYSFS_GT_PM_H__
> +
> +#include <linux/kobject.h>
> +
> +#include "intel_gt_types.h"
> +
> +void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj);
> +void intel_gt_sysfs_pm_remove(struct intel_gt *gt, struct kobject *kobj);
> +
> +#endif /* SYSFS_RC6_H */
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index ec76011366fb..f11acbc0990b 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -989,6 +989,8 @@ struct drm_i915_private {
>   #define I915_MAX_GT 4
>   	struct intel_gt *gt[I915_MAX_GT];
>   
> +	struct kobject *sysfs_gt;
> +
>   	struct {
>   		struct i915_gem_contexts {
>   			spinlock_t lock; /* locks list */
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index ef6bc8180073..5153b3ff41e9 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -8480,6 +8480,7 @@ enum {
>   #define   GEN6_AGGRESSIVE_TURBO			(0 << 15)
>   #define   GEN9_SW_REQ_UNSLICE_RATIO_SHIFT	23
>   #define   GEN9_IGNORE_SLICE_RATIO		(0 << 0)
> +#define   GEN12_SW_REQ_UNSLICE_RATIO_SHIFT	23

Stray something?

>   
>   #define GEN6_RC_VIDEO_FREQ			_MMIO(0xA00C)
>   #define GEN6_RC_CONTROL				_MMIO(0xA090)
> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
> index fae4d1f4f275..d6687e33f29d 100644
> --- a/drivers/gpu/drm/i915/i915_sysfs.c
> +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> @@ -38,113 +38,12 @@
>   #include "i915_sysfs.h"
>   #include "intel_pm.h"
>   
> -static inline struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
> +struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
>   {
>   	struct drm_minor *minor = dev_get_drvdata(kdev);
>   	return to_i915(minor->dev);
>   }
>   
> -#ifdef CONFIG_PM
> -static u32 calc_residency(struct drm_i915_private *dev_priv,
> -			  i915_reg_t reg)
> -{
> -	intel_wakeref_t wakeref;
> -	u64 res = 0;
> -
> -	with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref)
> -		res = intel_rc6_residency_us(&to_gt(dev_priv)->rc6, reg);
> -
> -	return DIV_ROUND_CLOSEST_ULL(res, 1000);
> -}
> -
> -static ssize_t rc6_enable_show(struct device *kdev,
> -			       struct device_attribute *attr, char *buf)
> -{
> -	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> -	unsigned int mask;
> -
> -	mask = 0;
> -	if (HAS_RC6(dev_priv))
> -		mask |= BIT(0);
> -	if (HAS_RC6p(dev_priv))
> -		mask |= BIT(1);
> -	if (HAS_RC6pp(dev_priv))
> -		mask |= BIT(2);
> -
> -	return sysfs_emit(buf, "%x\n", mask);
> -}
> -
> -static ssize_t rc6_residency_ms_show(struct device *kdev,
> -				     struct device_attribute *attr, char *buf)
> -{
> -	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> -	u32 rc6_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6);
> -	return sysfs_emit(buf, "%u\n", rc6_residency);
> -}
> -
> -static ssize_t rc6p_residency_ms_show(struct device *kdev,
> -				      struct device_attribute *attr, char *buf)
> -{
> -	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> -	u32 rc6p_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6p);
> -	return sysfs_emit(buf, "%u\n", rc6p_residency);
> -}
> -
> -static ssize_t rc6pp_residency_ms_show(struct device *kdev,
> -				       struct device_attribute *attr, char *buf)
> -{
> -	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> -	u32 rc6pp_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6pp);
> -	return sysfs_emit(buf, "%u\n", rc6pp_residency);
> -}
> -
> -static ssize_t media_rc6_residency_ms_show(struct device *kdev,
> -					   struct device_attribute *attr, char *buf)
> -{
> -	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> -	u32 rc6_residency = calc_residency(dev_priv, VLV_GT_MEDIA_RC6);
> -	return sysfs_emit(buf, "%u\n", rc6_residency);
> -}
> -
> -static DEVICE_ATTR_RO(rc6_enable);
> -static DEVICE_ATTR_RO(rc6_residency_ms);
> -static DEVICE_ATTR_RO(rc6p_residency_ms);
> -static DEVICE_ATTR_RO(rc6pp_residency_ms);
> -static DEVICE_ATTR_RO(media_rc6_residency_ms);
> -
> -static struct attribute *rc6_attrs[] = {
> -	&dev_attr_rc6_enable.attr,
> -	&dev_attr_rc6_residency_ms.attr,
> -	NULL
> -};
> -
> -static const struct attribute_group rc6_attr_group = {
> -	.name = power_group_name,
> -	.attrs =  rc6_attrs
> -};
> -
> -static struct attribute *rc6p_attrs[] = {
> -	&dev_attr_rc6p_residency_ms.attr,
> -	&dev_attr_rc6pp_residency_ms.attr,
> -	NULL
> -};
> -
> -static const struct attribute_group rc6p_attr_group = {
> -	.name = power_group_name,
> -	.attrs =  rc6p_attrs
> -};
> -
> -static struct attribute *media_rc6_attrs[] = {
> -	&dev_attr_media_rc6_residency_ms.attr,
> -	NULL
> -};
> -
> -static const struct attribute_group media_rc6_attr_group = {
> -	.name = power_group_name,
> -	.attrs =  media_rc6_attrs
> -};
> -#endif
> -
>   static int l3_access_valid(struct drm_i915_private *i915, loff_t offset)
>   {
>   	if (!HAS_L3_DPF(i915))
> @@ -256,171 +155,6 @@ static const struct bin_attribute dpf_attrs_1 = {
>   	.private = (void *)1
>   };
>   
> -static ssize_t gt_act_freq_mhz_show(struct device *kdev,
> -				    struct device_attribute *attr, char *buf)
> -{
> -	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
> -	struct intel_rps *rps = &to_gt(i915)->rps;
> -
> -	return sysfs_emit(buf, "%d\n", intel_rps_read_actual_frequency(rps));
> -}
> -
> -static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
> -				    struct device_attribute *attr, char *buf)
> -{
> -	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
> -	struct intel_rps *rps = &to_gt(i915)->rps;
> -
> -	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)
> -{
> -	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
> -	struct intel_rps *rps = &to_gt(i915)->rps;
> -
> -	return sysfs_emit(buf, "%d\n", intel_rps_get_boost_frequency(rps));
> -}
> -
> -static ssize_t gt_boost_freq_mhz_store(struct device *kdev,
> -				       struct device_attribute *attr,
> -				       const char *buf, size_t count)
> -{
> -	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> -	struct intel_rps *rps = &to_gt(dev_priv)->rps;
> -	ssize_t ret;
> -	u32 val;
> -
> -	ret = kstrtou32(buf, 0, &val);
> -	if (ret)
> -		return ret;
> -
> -	ret = intel_rps_set_boost_frequency(rps, val);
> -
> -	return ret ?: count;
> -}
> -
> -static ssize_t vlv_rpe_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 = &to_gt(dev_priv)->rps;
> -
> -	return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->efficient_freq));
> -}
> -
> -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_gt *gt = to_gt(dev_priv);
> -	struct intel_rps *rps = &gt->rps;
> -
> -	return sysfs_emit(buf, "%d\n", intel_rps_get_max_frequency(rps));
> -}
> -
> -static ssize_t gt_max_freq_mhz_store(struct device *kdev,
> -				     struct device_attribute *attr,
> -				     const char *buf, size_t count)
> -{
> -	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> -	struct intel_gt *gt = to_gt(dev_priv);
> -	struct intel_rps *rps = &gt->rps;
> -	ssize_t ret;
> -	u32 val;
> -
> -	ret = kstrtou32(buf, 0, &val);
> -	if (ret)
> -		return ret;
> -
> -	ret = intel_rps_set_max_frequency(rps, val);
> -
> -	return ret ?: count;
> -}
> -
> -static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
> -{
> -	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
> -	struct intel_gt *gt = to_gt(i915);
> -	struct intel_rps *rps = &gt->rps;
> -
> -	return sysfs_emit(buf, "%d\n", intel_rps_get_min_frequency(rps));
> -}
> -
> -static ssize_t gt_min_freq_mhz_store(struct device *kdev,
> -				     struct device_attribute *attr,
> -				     const char *buf, size_t count)
> -{
> -	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
> -	struct intel_rps *rps = &to_gt(i915)->rps;
> -	ssize_t ret;
> -	u32 val;
> -
> -	ret = kstrtou32(buf, 0, &val);
> -	if (ret)
> -		return ret;
> -
> -	ret = intel_rps_set_min_frequency(rps, val);
> -
> -	return ret ?: count;
> -}
> -
> -static DEVICE_ATTR_RO(gt_act_freq_mhz);
> -static DEVICE_ATTR_RO(gt_cur_freq_mhz);
> -static DEVICE_ATTR_RW(gt_boost_freq_mhz);
> -static DEVICE_ATTR_RW(gt_max_freq_mhz);
> -static DEVICE_ATTR_RW(gt_min_freq_mhz);
> -
> -static DEVICE_ATTR_RO(vlv_rpe_freq_mhz);
> -
> -static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf);
> -static DEVICE_ATTR(gt_RP0_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
> -static DEVICE_ATTR(gt_RP1_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
> -static DEVICE_ATTR(gt_RPn_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
> -
> -/* For now we have a static number of RP states */
> -static ssize_t gt_rp_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 = &to_gt(dev_priv)->rps;
> -	u32 val;
> -
> -	if (attr == &dev_attr_gt_RP0_freq_mhz)
> -		val = intel_rps_get_rp0_frequency(rps);
> -	else if (attr == &dev_attr_gt_RP1_freq_mhz)
> -		val = intel_rps_get_rp1_frequency(rps);
> -	else if (attr == &dev_attr_gt_RPn_freq_mhz)
> -		val = intel_rps_get_rpn_frequency(rps);
> -	else
> -		BUG();
> -
> -	return sysfs_emit(buf, "%d\n", val);
> -}
> -
> -static const struct attribute * const gen6_attrs[] = {
> -	&dev_attr_gt_act_freq_mhz.attr,
> -	&dev_attr_gt_cur_freq_mhz.attr,
> -	&dev_attr_gt_boost_freq_mhz.attr,
> -	&dev_attr_gt_max_freq_mhz.attr,
> -	&dev_attr_gt_min_freq_mhz.attr,
> -	&dev_attr_gt_RP0_freq_mhz.attr,
> -	&dev_attr_gt_RP1_freq_mhz.attr,
> -	&dev_attr_gt_RPn_freq_mhz.attr,
> -	NULL,
> -};
> -
> -static const struct attribute * const vlv_attrs[] = {
> -	&dev_attr_gt_act_freq_mhz.attr,
> -	&dev_attr_gt_cur_freq_mhz.attr,
> -	&dev_attr_gt_boost_freq_mhz.attr,
> -	&dev_attr_gt_max_freq_mhz.attr,
> -	&dev_attr_gt_min_freq_mhz.attr,
> -	&dev_attr_gt_RP0_freq_mhz.attr,
> -	&dev_attr_gt_RP1_freq_mhz.attr,
> -	&dev_attr_gt_RPn_freq_mhz.attr,
> -	&dev_attr_vlv_rpe_freq_mhz.attr,
> -	NULL,
> -};
> -
>   #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
>   
>   static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
> @@ -486,34 +220,16 @@ static void i915_setup_error_capture(struct device *kdev) {}
>   static void i915_teardown_error_capture(struct device *kdev) {}
>   #endif
>   
> +static struct kobject *i915_setup_gt_sysfs(struct kobject *parent)
> +{
> +	return kobject_create_and_add("gt", parent);
> +}
> +
>   void i915_setup_sysfs(struct drm_i915_private *dev_priv)
>   {
>   	struct device *kdev = dev_priv->drm.primary->kdev;
>   	int ret;
>   
> -#ifdef CONFIG_PM
> -	if (HAS_RC6(dev_priv)) {
> -		ret = sysfs_merge_group(&kdev->kobj,
> -					&rc6_attr_group);
> -		if (ret)
> -			drm_err(&dev_priv->drm,
> -				"RC6 residency sysfs setup failed\n");
> -	}
> -	if (HAS_RC6p(dev_priv)) {
> -		ret = sysfs_merge_group(&kdev->kobj,
> -					&rc6p_attr_group);
> -		if (ret)
> -			drm_err(&dev_priv->drm,
> -				"RC6p residency sysfs setup failed\n");
> -	}
> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> -		ret = sysfs_merge_group(&kdev->kobj,
> -					&media_rc6_attr_group);
> -		if (ret)
> -			drm_err(&dev_priv->drm,
> -				"Media RC6 residency sysfs setup failed\n");
> -	}
> -#endif
>   	if (HAS_L3_DPF(dev_priv)) {
>   		ret = device_create_bin_file(kdev, &dpf_attrs);
>   		if (ret)
> @@ -529,13 +245,10 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv)
>   		}
>   	}
>   
> -	ret = 0;
> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		ret = sysfs_create_files(&kdev->kobj, vlv_attrs);
> -	else if (GRAPHICS_VER(dev_priv) >= 6)
> -		ret = sysfs_create_files(&kdev->kobj, gen6_attrs);
> -	if (ret)
> -		drm_err(&dev_priv->drm, "RPS sysfs setup failed\n");
> +	dev_priv->sysfs_gt = i915_setup_gt_sysfs(&kdev->kobj);
> +	if (!dev_priv->sysfs_gt)
> +		drm_err(&dev_priv->drm,
> +			"failed to register GT sysfs directory\n");
>   
>   	i915_setup_error_capture(kdev);
>   
> @@ -548,14 +261,6 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv)
>   
>   	i915_teardown_error_capture(kdev);
>   
> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		sysfs_remove_files(&kdev->kobj, vlv_attrs);
> -	else
> -		sysfs_remove_files(&kdev->kobj, gen6_attrs);
>   	device_remove_bin_file(kdev,  &dpf_attrs_1);
>   	device_remove_bin_file(kdev,  &dpf_attrs);
> -#ifdef CONFIG_PM
> -	sysfs_unmerge_group(&kdev->kobj, &rc6_attr_group);
> -	sysfs_unmerge_group(&kdev->kobj, &rc6p_attr_group);
> -#endif
>   }
> diff --git a/drivers/gpu/drm/i915/i915_sysfs.h b/drivers/gpu/drm/i915/i915_sysfs.h
> index 41afd4366416..243a17741e3f 100644
> --- a/drivers/gpu/drm/i915/i915_sysfs.h
> +++ b/drivers/gpu/drm/i915/i915_sysfs.h
> @@ -6,8 +6,11 @@
>   #ifndef __I915_SYSFS_H__
>   #define __I915_SYSFS_H__
>   
> +struct device;
>   struct drm_i915_private;
>   
> +struct drm_i915_private *kdev_minor_to_i915(struct device *kdev);
> +
>   void i915_setup_sysfs(struct drm_i915_private *i915);
>   void i915_teardown_sysfs(struct drm_i915_private *i915);
>   
> 

Regards,

Tvrtko

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

* [Intel-gfx] ✗ Fi.CI.BAT: failure for Introduce multitile support
  2022-01-17 15:09 ` [Intel-gfx] " Andi Shyti
                   ` (4 preceding siblings ...)
  (?)
@ 2022-01-17 16:09 ` Patchwork
  -1 siblings, 0 replies; 17+ messages in thread
From: Patchwork @ 2022-01-17 16:09 UTC (permalink / raw)
  To: Andi Shyti; +Cc: intel-gfx

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

== Series Details ==

Series: Introduce multitile support
URL   : https://patchwork.freedesktop.org/series/98950/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_11091 -> Patchwork_22007
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with Patchwork_22007 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_22007, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/index.html

Participating hosts (47 -> 42)
------------------------------

  Additional (1): bat-jsl-2 
  Missing    (6): shard-tglu fi-bsw-cyan fi-pnv-d510 shard-rkl shard-dg1 fi-bdw-samus 

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_22007:

### IGT changes ###

#### Possible regressions ####

  * igt@i915_selftest@live@gtt:
    - fi-bdw-5557u:       [PASS][1] -> [DMESG-FAIL][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/fi-bdw-5557u/igt@i915_selftest@live@gtt.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/fi-bdw-5557u/igt@i915_selftest@live@gtt.html

  
Known issues
------------

  Here are the changes found in Patchwork_22007 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@amdgpu/amd_basic@cs-sdma:
    - fi-kbl-8809g:       [PASS][3] -> [SKIP][4] ([fdo#109271]) +16 similar issues
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/fi-kbl-8809g/igt@amdgpu/amd_basic@cs-sdma.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/fi-kbl-8809g/igt@amdgpu/amd_basic@cs-sdma.html

  * igt@gem_flink_basic@bad-flink:
    - fi-skl-6600u:       [PASS][5] -> [INCOMPLETE][6] ([i915#4547])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/fi-skl-6600u/igt@gem_flink_basic@bad-flink.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/fi-skl-6600u/igt@gem_flink_basic@bad-flink.html

  * igt@i915_selftest@live@execlists:
    - fi-bsw-nick:        [PASS][7] -> [INCOMPLETE][8] ([i915#2940])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/fi-bsw-nick/igt@i915_selftest@live@execlists.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/fi-bsw-nick/igt@i915_selftest@live@execlists.html

  * igt@i915_selftest@live@gt_heartbeat:
    - fi-bdw-5557u:       [PASS][9] -> [DMESG-FAIL][10] ([i915#541])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/fi-bdw-5557u/igt@i915_selftest@live@gt_heartbeat.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/fi-bdw-5557u/igt@i915_selftest@live@gt_heartbeat.html

  * igt@kms_addfb_basic@addfb25-y-tiled-small-legacy:
    - fi-snb-2600:        NOTRUN -> [SKIP][11] ([fdo#109271]) +37 similar issues
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/fi-snb-2600/igt@kms_addfb_basic@addfb25-y-tiled-small-legacy.html

  * igt@kms_chamelium@hdmi-crc-fast:
    - fi-snb-2600:        NOTRUN -> [SKIP][12] ([fdo#109271] / [fdo#111827]) +8 similar issues
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/fi-snb-2600/igt@kms_chamelium@hdmi-crc-fast.html

  * igt@runner@aborted:
    - fi-skl-6600u:       NOTRUN -> [FAIL][13] ([i915#2722] / [i915#4312])
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/fi-skl-6600u/igt@runner@aborted.html
    - fi-bsw-nick:        NOTRUN -> [FAIL][14] ([fdo#109271] / [i915#1436] / [i915#2722] / [i915#3428] / [i915#4312])
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/fi-bsw-nick/igt@runner@aborted.html

  
#### Possible fixes ####

  * igt@i915_module_load@reload:
    - fi-kbl-soraka:      [DMESG-WARN][15] ([i915#1982]) -> [PASS][16]
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/fi-kbl-soraka/igt@i915_module_load@reload.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/fi-kbl-soraka/igt@i915_module_load@reload.html

  * igt@i915_selftest@live@hangcheck:
    - bat-dg1-5:          [DMESG-FAIL][17] ([i915#4494]) -> [PASS][18]
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/bat-dg1-5/igt@i915_selftest@live@hangcheck.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/bat-dg1-5/igt@i915_selftest@live@hangcheck.html

  * igt@kms_frontbuffer_tracking@basic:
    - fi-cml-u2:          [DMESG-WARN][19] ([i915#4269]) -> [PASS][20]
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/fi-cml-u2/igt@kms_frontbuffer_tracking@basic.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/fi-cml-u2/igt@kms_frontbuffer_tracking@basic.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109285]: https://bugs.freedesktop.org/show_bug.cgi?id=109285
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [i915#1436]: https://gitlab.freedesktop.org/drm/intel/issues/1436
  [i915#1982]: https://gitlab.freedesktop.org/drm/intel/issues/1982
  [i915#2190]: https://gitlab.freedesktop.org/drm/intel/issues/2190
  [i915#2722]: https://gitlab.freedesktop.org/drm/intel/issues/2722
  [i915#2940]: https://gitlab.freedesktop.org/drm/intel/issues/2940
  [i915#3301]: https://gitlab.freedesktop.org/drm/intel/issues/3301
  [i915#3428]: https://gitlab.freedesktop.org/drm/intel/issues/3428
  [i915#4103]: https://gitlab.freedesktop.org/drm/intel/issues/4103
  [i915#4269]: https://gitlab.freedesktop.org/drm/intel/issues/4269
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#4494]: https://gitlab.freedesktop.org/drm/intel/issues/4494
  [i915#4547]: https://gitlab.freedesktop.org/drm/intel/issues/4547
  [i915#4613]: https://gitlab.freedesktop.org/drm/intel/issues/4613
  [i915#533]: https://gitlab.freedesktop.org/drm/intel/issues/533
  [i915#541]: https://gitlab.freedesktop.org/drm/intel/issues/541


Build changes
-------------

  * Linux: CI_DRM_11091 -> Patchwork_22007

  CI-20190529: 20190529
  CI_DRM_11091: 11b3d8ac8a78d74ce7559fd2046a89166b0c70b1 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_6327: 0d559158c2d3b5723abbfc2cb4b04532e28663b2 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_22007: 9028d350f2066f9a4b3de849c7968e36e19367cb @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

9028d350f206 drm/i915/gt: make a gt sysfs group and move power management files
28afa8633a19 drm/i915: Prepare for multiple GTs

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/index.html

[-- Attachment #2: Type: text/html, Size: 7716 bytes --]

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

* Re: [Intel-gfx] [PATCH v3 2/2] drm/i915/gt: make a gt sysfs group and move power management files
  2022-01-17 16:02   ` Tvrtko Ursulin
@ 2022-01-17 17:16       ` Andi Shyti
  2022-01-19  7:19       ` Joonas Lahtinen
  1 sibling, 0 replies; 17+ messages in thread
From: Andi Shyti @ 2022-01-17 17:16 UTC (permalink / raw)
  To: Tvrtko Ursulin
  Cc: Abdiel Janulgue, Intel GFX, Lucas De Marchi, DRI Devel,
	Matthew Auld, Andi Shyti

Hi Tvrtko,

> > The previous power management files are kept in their original
> > root directory to avoid breaking the ABI. They point to the tile
> > '0' and a warning message is printed whenever accessed to. The
> > deprecated interface needs for the CONFIG_SYSFS_DEPRECATED_V2
> > flag in order to be generated.
> 
> CONFIG_SYSFS_DEPRECATED_V2 idea was abandoned, no? This patch at least does
> not appear to contain it so please update the commit message to reflect
> current state.
> 
> Adding Joonas to help address the question of how strict are userspace
> requirements for sysfs additions. Personally sysadmin use sounds fine to me,
> although it needs to be mentioned/documented as Matt requested, but I fear
> it may not be enough to upstream. Is Level0 at the stage where we can
> upstream for it I am also not sure.

no need... it's a leftover in the commit message. The deprecated
was removed a year ago, maybe. Thanks!

[...]

> > +		pr_devel_ratelimited(DEPRECATED
> > +			"%s (pid %d) is trying to access deprecated %s "
> > +			"sysfs control, please use gt/gt<n>/%s instead\n",
> 
> Maybe reword "is trying to access" to "is accesing" to remove any doubt
> whether something is failing or not?

OK

[...]

> > +	if (sysfs_create_file(dir, &dev_attr_id.attr))
> > +		drm_err(&gt->i915->drm,
> > +			"failed to create sysfs %s info files\n", name);
> 
> These drm_err could maybe be warn or notice, to reflect the fact driver is
> most likely completely functional? But only maybe since I haven't checked
> what we do for other sysfs failures. If rest are drm_err then I guess
> consistency trumps it.

yes, I agree with you and indeed they whould be treated as
warnings because the driver probes correctly if sysfs fails.

I will change this to drm_warn and fixx all the others. Thanks!

[...]

> > +static inline bool is_object_gt(struct kobject *kobj)
> > +{
> > +	bool b = !strncmp(kobj->name, "gt", 2);
> > +
> > +	GEM_BUG_ON(b && !isdigit(kobj->name[2]));
> 
> 1)
> Not sure what is the point of this GEM_BUG_ON? Checking strncmp works feels
> like an overkill.
> 
> 2)
> With the recent trend of "static inline considered harmful" perhaps consider
> moving it out of line.

OK

[...]

> > +static const struct attribute_group rc6_attr_group[] = {
> > +	{ .name = power_group_name, .attrs = rc6_attrs },
> > +	{ .attrs = rc6_attrs }
> > +};
> > +
> > +static const struct attribute_group rc6p_attr_group[] = {
> > +	{ .name = power_group_name, .attrs = rc6p_attrs },
> > +	{ .attrs = rc6p_attrs }
> > +};
> > +
> > +static const struct attribute_group media_rc6_attr_group[] = {
> > +	{ .name = power_group_name, .attrs = media_rc6_attrs },
> > +	{ .attrs = media_rc6_attrs }
> > +};
> > +
> > +static int __intel_gt_sysfs_create_group(struct kobject *kobj,
> > +					 const struct attribute_group *grp)
> > +{
> > +	int i = is_object_gt(kobj);
> 
> Is_object_gt returns a bool so can I be pedantic? :) Maybe just omit the
> local and solve it like that.

'i' is used also as an array index here, and callse merge/create
depending on what kind of object kobj is.

Maybe it's a bit of an ugly trick, but perhaps to mark the fact I
can do it like

	i = !!is_object_gt(kobj);

> > +
> > +	return i ? sysfs_create_group(kobj, &grp[i]) :
> > +		   sysfs_merge_group(kobj, &grp[i]);
> > +}
> > +
> > +static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj)
> > +{
> > +	int ret;
> > +
> > +	if (!HAS_RC6(gt->i915))
> > +		return;
> > +
> > +	ret = __intel_gt_sysfs_create_group(kobj, rc6_attr_group);
> > +	if (ret)
> > +		drm_err(&gt->i915->drm,
> > +			"failed to create gt%u RC6 sysfs files\n", gt->info.id);
> > +
> > +	if (HAS_RC6p(gt->i915)) {
> > +		ret = __intel_gt_sysfs_create_group(kobj, rc6p_attr_group);
> > +		if (ret)
> > +			drm_err(&gt->i915->drm,
> > +				"failed to create gt%u RC6p sysfs files\n",
> > +				gt->info.id);
> > +	}
> > +
> > +	if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915)) {
> > +		ret = __intel_gt_sysfs_create_group(kobj, media_rc6_attr_group);
> > +		if (ret)
> > +			drm_err(&gt->i915->drm,
> > +				"failed to create media %u RC6 sysfs files\n",
> > +				gt->info.id);
> > +	}
> > +}

[...]

> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -8480,6 +8480,7 @@ enum {
> >   #define   GEN6_AGGRESSIVE_TURBO			(0 << 15)
> >   #define   GEN9_SW_REQ_UNSLICE_RATIO_SHIFT	23
> >   #define   GEN9_IGNORE_SLICE_RATIO		(0 << 0)
> > +#define   GEN12_SW_REQ_UNSLICE_RATIO_SHIFT	23
> 
> Stray something?

I don't know how this ended up here... scary!

> Regards,
> 
> Tvrtko

Thanks a lot for looking again into this!

Andi

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

* Re: [Intel-gfx] [PATCH v3 2/2] drm/i915/gt: make a gt sysfs group and move power management files
@ 2022-01-17 17:16       ` Andi Shyti
  0 siblings, 0 replies; 17+ messages in thread
From: Andi Shyti @ 2022-01-17 17:16 UTC (permalink / raw)
  To: Tvrtko Ursulin
  Cc: Abdiel Janulgue, Intel GFX, Lucas De Marchi, DRI Devel, Matthew Auld

Hi Tvrtko,

> > The previous power management files are kept in their original
> > root directory to avoid breaking the ABI. They point to the tile
> > '0' and a warning message is printed whenever accessed to. The
> > deprecated interface needs for the CONFIG_SYSFS_DEPRECATED_V2
> > flag in order to be generated.
> 
> CONFIG_SYSFS_DEPRECATED_V2 idea was abandoned, no? This patch at least does
> not appear to contain it so please update the commit message to reflect
> current state.
> 
> Adding Joonas to help address the question of how strict are userspace
> requirements for sysfs additions. Personally sysadmin use sounds fine to me,
> although it needs to be mentioned/documented as Matt requested, but I fear
> it may not be enough to upstream. Is Level0 at the stage where we can
> upstream for it I am also not sure.

no need... it's a leftover in the commit message. The deprecated
was removed a year ago, maybe. Thanks!

[...]

> > +		pr_devel_ratelimited(DEPRECATED
> > +			"%s (pid %d) is trying to access deprecated %s "
> > +			"sysfs control, please use gt/gt<n>/%s instead\n",
> 
> Maybe reword "is trying to access" to "is accesing" to remove any doubt
> whether something is failing or not?

OK

[...]

> > +	if (sysfs_create_file(dir, &dev_attr_id.attr))
> > +		drm_err(&gt->i915->drm,
> > +			"failed to create sysfs %s info files\n", name);
> 
> These drm_err could maybe be warn or notice, to reflect the fact driver is
> most likely completely functional? But only maybe since I haven't checked
> what we do for other sysfs failures. If rest are drm_err then I guess
> consistency trumps it.

yes, I agree with you and indeed they whould be treated as
warnings because the driver probes correctly if sysfs fails.

I will change this to drm_warn and fixx all the others. Thanks!

[...]

> > +static inline bool is_object_gt(struct kobject *kobj)
> > +{
> > +	bool b = !strncmp(kobj->name, "gt", 2);
> > +
> > +	GEM_BUG_ON(b && !isdigit(kobj->name[2]));
> 
> 1)
> Not sure what is the point of this GEM_BUG_ON? Checking strncmp works feels
> like an overkill.
> 
> 2)
> With the recent trend of "static inline considered harmful" perhaps consider
> moving it out of line.

OK

[...]

> > +static const struct attribute_group rc6_attr_group[] = {
> > +	{ .name = power_group_name, .attrs = rc6_attrs },
> > +	{ .attrs = rc6_attrs }
> > +};
> > +
> > +static const struct attribute_group rc6p_attr_group[] = {
> > +	{ .name = power_group_name, .attrs = rc6p_attrs },
> > +	{ .attrs = rc6p_attrs }
> > +};
> > +
> > +static const struct attribute_group media_rc6_attr_group[] = {
> > +	{ .name = power_group_name, .attrs = media_rc6_attrs },
> > +	{ .attrs = media_rc6_attrs }
> > +};
> > +
> > +static int __intel_gt_sysfs_create_group(struct kobject *kobj,
> > +					 const struct attribute_group *grp)
> > +{
> > +	int i = is_object_gt(kobj);
> 
> Is_object_gt returns a bool so can I be pedantic? :) Maybe just omit the
> local and solve it like that.

'i' is used also as an array index here, and callse merge/create
depending on what kind of object kobj is.

Maybe it's a bit of an ugly trick, but perhaps to mark the fact I
can do it like

	i = !!is_object_gt(kobj);

> > +
> > +	return i ? sysfs_create_group(kobj, &grp[i]) :
> > +		   sysfs_merge_group(kobj, &grp[i]);
> > +}
> > +
> > +static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj)
> > +{
> > +	int ret;
> > +
> > +	if (!HAS_RC6(gt->i915))
> > +		return;
> > +
> > +	ret = __intel_gt_sysfs_create_group(kobj, rc6_attr_group);
> > +	if (ret)
> > +		drm_err(&gt->i915->drm,
> > +			"failed to create gt%u RC6 sysfs files\n", gt->info.id);
> > +
> > +	if (HAS_RC6p(gt->i915)) {
> > +		ret = __intel_gt_sysfs_create_group(kobj, rc6p_attr_group);
> > +		if (ret)
> > +			drm_err(&gt->i915->drm,
> > +				"failed to create gt%u RC6p sysfs files\n",
> > +				gt->info.id);
> > +	}
> > +
> > +	if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915)) {
> > +		ret = __intel_gt_sysfs_create_group(kobj, media_rc6_attr_group);
> > +		if (ret)
> > +			drm_err(&gt->i915->drm,
> > +				"failed to create media %u RC6 sysfs files\n",
> > +				gt->info.id);
> > +	}
> > +}

[...]

> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -8480,6 +8480,7 @@ enum {
> >   #define   GEN6_AGGRESSIVE_TURBO			(0 << 15)
> >   #define   GEN9_SW_REQ_UNSLICE_RATIO_SHIFT	23
> >   #define   GEN9_IGNORE_SLICE_RATIO		(0 << 0)
> > +#define   GEN12_SW_REQ_UNSLICE_RATIO_SHIFT	23
> 
> Stray something?

I don't know how this ended up here... scary!

> Regards,
> 
> Tvrtko

Thanks a lot for looking again into this!

Andi

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

* [Intel-gfx] ✗ Fi.CI.IGT: failure for Introduce multitile support
  2022-01-17 15:09 ` [Intel-gfx] " Andi Shyti
                   ` (5 preceding siblings ...)
  (?)
@ 2022-01-17 17:57 ` Patchwork
  -1 siblings, 0 replies; 17+ messages in thread
From: Patchwork @ 2022-01-17 17:57 UTC (permalink / raw)
  To: Andi Shyti; +Cc: intel-gfx

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

== Series Details ==

Series: Introduce multitile support
URL   : https://patchwork.freedesktop.org/series/98950/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_11091_full -> Patchwork_22007_full
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with Patchwork_22007_full absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_22007_full, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

Participating hosts (13 -> 13)
------------------------------

  No changes in participating hosts

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_22007_full:

### IGT changes ###

#### Possible regressions ####

  * igt@i915_selftest@mock@requests:
    - shard-kbl:          [PASS][1] -> [DMESG-FAIL][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-kbl7/igt@i915_selftest@mock@requests.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-kbl4/igt@i915_selftest@mock@requests.html
    - shard-apl:          [PASS][3] -> ([DMESG-FAIL][4], [DMESG-FAIL][5])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-apl2/igt@i915_selftest@mock@requests.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-apl4/igt@i915_selftest@mock@requests.html
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-apl8/igt@i915_selftest@mock@requests.html
    - shard-snb:          [PASS][6] -> [DMESG-FAIL][7]
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-snb6/igt@i915_selftest@mock@requests.html
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-snb6/igt@i915_selftest@mock@requests.html
    - shard-iclb:         [PASS][8] -> [DMESG-FAIL][9]
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-iclb5/igt@i915_selftest@mock@requests.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-iclb6/igt@i915_selftest@mock@requests.html

  * igt@sysfs_heartbeat_interval@nopreempt@rcs0:
    - shard-tglb:         [PASS][10] -> [FAIL][11]
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-tglb2/igt@sysfs_heartbeat_interval@nopreempt@rcs0.html
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-tglb2/igt@sysfs_heartbeat_interval@nopreempt@rcs0.html

  
#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@gem_ctx_shared@q-smoketest-all:
    - {shard-rkl}:        [INCOMPLETE][12] -> ([PASS][13], [INCOMPLETE][14])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-5/igt@gem_ctx_shared@q-smoketest-all.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-4/igt@gem_ctx_shared@q-smoketest-all.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-5/igt@gem_ctx_shared@q-smoketest-all.html

  * igt@gem_exec_create@forked@smem:
    - {shard-tglu}:       [PASS][15] -> [DMESG-FAIL][16]
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-tglu-2/igt@gem_exec_create@forked@smem.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-tglu-7/igt@gem_exec_create@forked@smem.html

  * igt@gem_exec_create@madvise@smem:
    - {shard-rkl}:        ([PASS][17], [PASS][18]) -> [INCOMPLETE][19]
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-4/igt@gem_exec_create@madvise@smem.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-2/igt@gem_exec_create@madvise@smem.html
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-5/igt@gem_exec_create@madvise@smem.html

  * igt@gem_exec_schedule@smoketest-all:
    - {shard-rkl}:        NOTRUN -> [INCOMPLETE][20]
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-5/igt@gem_exec_schedule@smoketest-all.html

  * igt@gem_exec_whisper@basic-queues-forked:
    - {shard-rkl}:        [PASS][21] -> [INCOMPLETE][22]
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-1/igt@gem_exec_whisper@basic-queues-forked.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-5/igt@gem_exec_whisper@basic-queues-forked.html

  * igt@i915_selftest@live@gt_pm:
    - {shard-rkl}:        [PASS][23] -> [DMESG-FAIL][24]
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-4/igt@i915_selftest@live@gt_pm.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-6/igt@i915_selftest@live@gt_pm.html

  * igt@i915_selftest@live@hangcheck:
    - {shard-dg1}:        [PASS][25] -> [DMESG-FAIL][26]
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-dg1-17/igt@i915_selftest@live@hangcheck.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-dg1-18/igt@i915_selftest@live@hangcheck.html

  * igt@runner@aborted:
    - {shard-tglu}:       ([FAIL][27], [FAIL][28], [FAIL][29]) ([i915#3002] / [i915#4312]) -> ([FAIL][30], [FAIL][31], [FAIL][32], [FAIL][33]) ([i915#2722] / [i915#3002] / [i915#4312])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-tglu-3/igt@runner@aborted.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-tglu-4/igt@runner@aborted.html
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-tglu-7/igt@runner@aborted.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-tglu-5/igt@runner@aborted.html
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-tglu-1/igt@runner@aborted.html
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-tglu-7/igt@runner@aborted.html
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-tglu-7/igt@runner@aborted.html

  
New tests
---------

  New tests have been introduced between CI_DRM_11091_full and Patchwork_22007_full:

### New IGT tests (2) ###

  * igt@gem_spin_batch@legacy-resubmit:
    - Statuses :
    - Exec time: [None] s

  * igt@gem_spin_batch@legacy-resubmit-new:
    - Statuses :
    - Exec time: [None] s

  

Known issues
------------

  Here are the changes found in Patchwork_22007_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_ctx_persistence@smoketest:
    - shard-iclb:         [PASS][34] -> [FAIL][35] ([i915#2896])
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-iclb6/igt@gem_ctx_persistence@smoketest.html
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-iclb1/igt@gem_ctx_persistence@smoketest.html

  * igt@gem_eio@kms:
    - shard-tglb:         [PASS][36] -> [FAIL][37] ([i915#232])
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-tglb7/igt@gem_eio@kms.html
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-tglb5/igt@gem_eio@kms.html

  * igt@gem_exec_balancer@parallel-contexts:
    - shard-iclb:         [PASS][38] -> [SKIP][39] ([i915#4525])
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-iclb1/igt@gem_exec_balancer@parallel-contexts.html
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-iclb7/igt@gem_exec_balancer@parallel-contexts.html

  * igt@gem_exec_capture@pi@rcs0:
    - shard-skl:          [PASS][40] -> [INCOMPLETE][41] ([i915#4547])
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-skl5/igt@gem_exec_capture@pi@rcs0.html
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl2/igt@gem_exec_capture@pi@rcs0.html

  * igt@gem_exec_fair@basic-deadline:
    - shard-skl:          NOTRUN -> [FAIL][42] ([i915#2846])
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl8/igt@gem_exec_fair@basic-deadline.html

  * igt@gem_exec_fair@basic-flow@rcs0:
    - shard-skl:          NOTRUN -> [SKIP][43] ([fdo#109271]) +245 similar issues
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl2/igt@gem_exec_fair@basic-flow@rcs0.html

  * igt@gem_exec_fair@basic-pace@vcs1:
    - shard-kbl:          [PASS][44] -> [FAIL][45] ([i915#2842])
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-kbl1/igt@gem_exec_fair@basic-pace@vcs1.html
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-kbl6/igt@gem_exec_fair@basic-pace@vcs1.html

  * igt@gem_huc_copy@huc-copy:
    - shard-kbl:          NOTRUN -> [SKIP][46] ([fdo#109271] / [i915#2190])
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-kbl1/igt@gem_huc_copy@huc-copy.html

  * igt@gem_lmem_swapping@heavy-verify-random:
    - shard-skl:          NOTRUN -> [SKIP][47] ([fdo#109271] / [i915#4613]) +3 similar issues
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl7/igt@gem_lmem_swapping@heavy-verify-random.html

  * igt@gem_lmem_swapping@parallel-random-verify:
    - shard-kbl:          NOTRUN -> [SKIP][48] ([fdo#109271] / [i915#4613]) +1 similar issue
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-kbl3/igt@gem_lmem_swapping@parallel-random-verify.html
    - shard-apl:          NOTRUN -> [SKIP][49] ([fdo#109271] / [i915#4613])
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-apl6/igt@gem_lmem_swapping@parallel-random-verify.html

  * igt@gem_softpin@noreloc-s3:
    - shard-kbl:          NOTRUN -> [DMESG-WARN][50] ([i915#180])
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-kbl1/igt@gem_softpin@noreloc-s3.html

  * igt@gem_userptr_blits@input-checking:
    - shard-skl:          NOTRUN -> [DMESG-WARN][51] ([i915#3002])
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl6/igt@gem_userptr_blits@input-checking.html

  * igt@i915_pm_dc@dc6-dpms:
    - shard-skl:          NOTRUN -> [FAIL][52] ([i915#454])
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl10/igt@i915_pm_dc@dc6-dpms.html

  * igt@i915_selftest@live@gt_pm:
    - shard-skl:          NOTRUN -> [DMESG-FAIL][53] ([i915#1886] / [i915#2291])
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl4/igt@i915_selftest@live@gt_pm.html

  * igt@kms_async_flips@alternate-sync-async-flip:
    - shard-skl:          [PASS][54] -> [FAIL][55] ([i915#2521])
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-skl10/igt@kms_async_flips@alternate-sync-async-flip.html
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl9/igt@kms_async_flips@alternate-sync-async-flip.html

  * igt@kms_big_fb@linear-32bpp-rotate-180:
    - shard-glk:          [PASS][56] -> [DMESG-WARN][57] ([i915#118]) +2 similar issues
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-glk6/igt@kms_big_fb@linear-32bpp-rotate-180.html
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-glk2/igt@kms_big_fb@linear-32bpp-rotate-180.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip:
    - shard-skl:          NOTRUN -> [SKIP][58] ([fdo#109271] / [i915#3777]) +1 similar issue
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl4/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip.html

  * igt@kms_ccs@pipe-a-bad-rotation-90-y_tiled_gen12_mc_ccs:
    - shard-kbl:          NOTRUN -> [SKIP][59] ([fdo#109271] / [i915#3886])
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-kbl3/igt@kms_ccs@pipe-a-bad-rotation-90-y_tiled_gen12_mc_ccs.html

  * igt@kms_ccs@pipe-a-crc-primary-rotation-180-y_tiled_gen12_rc_ccs_cc:
    - shard-skl:          NOTRUN -> [SKIP][60] ([fdo#109271] / [i915#3886]) +9 similar issues
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl10/igt@kms_ccs@pipe-a-crc-primary-rotation-180-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_chamelium@vga-hpd-after-suspend:
    - shard-skl:          NOTRUN -> [SKIP][61] ([fdo#109271] / [fdo#111827]) +20 similar issues
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl6/igt@kms_chamelium@vga-hpd-after-suspend.html

  * igt@kms_color_chamelium@pipe-a-ctm-0-75:
    - shard-kbl:          NOTRUN -> [SKIP][62] ([fdo#109271] / [fdo#111827]) +6 similar issues
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-kbl3/igt@kms_color_chamelium@pipe-a-ctm-0-75.html

  * igt@kms_color_chamelium@pipe-b-ctm-limited-range:
    - shard-apl:          NOTRUN -> [SKIP][63] ([fdo#109271] / [fdo#111827]) +2 similar issues
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-apl6/igt@kms_color_chamelium@pipe-b-ctm-limited-range.html

  * igt@kms_cursor_crc@pipe-a-cursor-suspend:
    - shard-kbl:          [PASS][64] -> [DMESG-WARN][65] ([i915#180]) +2 similar issues
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-kbl3/igt@kms_cursor_crc@pipe-a-cursor-suspend.html
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-kbl4/igt@kms_cursor_crc@pipe-a-cursor-suspend.html
    - shard-apl:          [PASS][66] -> [DMESG-WARN][67] ([i915#180])
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-apl6/igt@kms_cursor_crc@pipe-a-cursor-suspend.html
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-apl3/igt@kms_cursor_crc@pipe-a-cursor-suspend.html

  * igt@kms_cursor_edge_walk@pipe-a-128x128-top-edge:
    - shard-skl:          [PASS][68] -> [DMESG-WARN][69] ([i915#1982]) +1 similar issue
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-skl4/igt@kms_cursor_edge_walk@pipe-a-128x128-top-edge.html
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl7/igt@kms_cursor_edge_walk@pipe-a-128x128-top-edge.html

  * igt@kms_fbcon_fbt@fbc-suspend:
    - shard-kbl:          [PASS][70] -> [INCOMPLETE][71] ([i915#180] / [i915#636])
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-kbl3/igt@kms_fbcon_fbt@fbc-suspend.html
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-kbl4/igt@kms_fbcon_fbt@fbc-suspend.html

  * igt@kms_flip@flip-vs-expired-vblank-interruptible@c-edp1:
    - shard-skl:          NOTRUN -> [FAIL][72] ([i915#79])
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl10/igt@kms_flip@flip-vs-expired-vblank-interruptible@c-edp1.html

  * igt@kms_flip@plain-flip-fb-recreate-interruptible@c-edp1:
    - shard-skl:          NOTRUN -> [FAIL][73] ([i915#2122]) +1 similar issue
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl3/igt@kms_flip@plain-flip-fb-recreate-interruptible@c-edp1.html

  * igt@kms_flip@plain-flip-fb-recreate@c-edp1:
    - shard-skl:          [PASS][74] -> [FAIL][75] ([i915#2122]) +1 similar issue
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-skl5/igt@kms_flip@plain-flip-fb-recreate@c-edp1.html
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl2/igt@kms_flip@plain-flip-fb-recreate@c-edp1.html

  * igt@kms_frontbuffer_tracking@fbc-suspend:
    - shard-apl:          [PASS][76] -> ([DMESG-WARN][77], [PASS][78]) ([i915#180])
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-apl7/igt@kms_frontbuffer_tracking@fbc-suspend.html
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-apl7/igt@kms_frontbuffer_tracking@fbc-suspend.html
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-apl3/igt@kms_frontbuffer_tracking@fbc-suspend.html

  * igt@kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-draw-blt:
    - shard-apl:          NOTRUN -> [SKIP][79] ([fdo#109271]) +29 similar issues
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-apl6/igt@kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-draw-blt.html

  * igt@kms_hdr@bpc-switch-dpms:
    - shard-skl:          NOTRUN -> [FAIL][80] ([i915#1188]) +1 similar issue
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl8/igt@kms_hdr@bpc-switch-dpms.html

  * igt@kms_panel_fitting@legacy:
    - shard-kbl:          NOTRUN -> [SKIP][81] ([fdo#109271]) +81 similar issues
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-kbl3/igt@kms_panel_fitting@legacy.html

  * igt@kms_pipe_crc_basic@hang-read-crc-pipe-d:
    - shard-skl:          NOTRUN -> [SKIP][82] ([fdo#109271] / [i915#533]) +2 similar issues
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl8/igt@kms_pipe_crc_basic@hang-read-crc-pipe-d.html

  * igt@kms_pipe_crc_basic@suspend-read-crc-pipe-a:
    - shard-kbl:          [PASS][83] -> [INCOMPLETE][84] ([i915#794])
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-kbl6/igt@kms_pipe_crc_basic@suspend-read-crc-pipe-a.html
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-kbl4/igt@kms_pipe_crc_basic@suspend-read-crc-pipe-a.html

  * igt@kms_plane_alpha_blend@pipe-c-constant-alpha-max:
    - shard-kbl:          NOTRUN -> [FAIL][85] ([fdo#108145] / [i915#265])
   [85]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-kbl3/igt@kms_plane_alpha_blend@pipe-c-constant-alpha-max.html

  * igt@kms_plane_alpha_blend@pipe-c-coverage-7efc:
    - shard-skl:          NOTRUN -> [FAIL][86] ([fdo#108145] / [i915#265]) +2 similar issues
   [86]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl10/igt@kms_plane_alpha_blend@pipe-c-coverage-7efc.html

  * igt@kms_psr2_sf@cursor-plane-update-sf:
    - shard-skl:          NOTRUN -> [SKIP][87] ([fdo#109271] / [i915#658])
   [87]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl3/igt@kms_psr2_sf@cursor-plane-update-sf.html
    - shard-apl:          NOTRUN -> [SKIP][88] ([fdo#109271] / [i915#658])
   [88]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-apl6/igt@kms_psr2_sf@cursor-plane-update-sf.html

  * igt@kms_psr2_sf@overlay-plane-update-sf-dmg-area:
    - shard-kbl:          NOTRUN -> [SKIP][89] ([fdo#109271] / [i915#658]) +1 similar issue
   [89]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-kbl3/igt@kms_psr2_sf@overlay-plane-update-sf-dmg-area.html

  * igt@kms_psr@psr2_cursor_blt:
    - shard-iclb:         [PASS][90] -> [SKIP][91] ([fdo#109441])
   [90]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-iclb2/igt@kms_psr@psr2_cursor_blt.html
   [91]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-iclb4/igt@kms_psr@psr2_cursor_blt.html

  * igt@kms_vblank@pipe-a-ts-continuation-dpms-suspend:
    - shard-skl:          [PASS][92] -> [INCOMPLETE][93] ([i915#4939]) +1 similar issue
   [92]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-skl6/igt@kms_vblank@pipe-a-ts-continuation-dpms-suspend.html
   [93]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl8/igt@kms_vblank@pipe-a-ts-continuation-dpms-suspend.html

  * igt@kms_writeback@writeback-pixel-formats:
    - shard-skl:          NOTRUN -> [SKIP][94] ([fdo#109271] / [i915#2437])
   [94]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl2/igt@kms_writeback@writeback-pixel-formats.html

  * igt@sysfs_clients@create:
    - shard-kbl:          NOTRUN -> [SKIP][95] ([fdo#109271] / [i915#2994]) +2 similar issues
   [95]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-kbl3/igt@sysfs_clients@create.html

  * igt@sysfs_clients@fair-0:
    - shard-skl:          NOTRUN -> [SKIP][96] ([fdo#109271] / [i915#2994]) +4 similar issues
   [96]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl3/igt@sysfs_clients@fair-0.html
    - shard-apl:          NOTRUN -> [SKIP][97] ([fdo#109271] / [i915#2994])
   [97]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-apl6/igt@sysfs_clients@fair-0.html

  
#### Possible fixes ####

  * igt@gem_create@create-ext-placement-sanity-check:
    - {shard-rkl}:        [FAIL][98] -> [PASS][99] +10 similar issues
   [98]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-5/igt@gem_create@create-ext-placement-sanity-check.html
   [99]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-2/igt@gem_create@create-ext-placement-sanity-check.html

  * igt@gem_exec_fence@syncobj-wait:
    - {shard-rkl}:        [FAIL][100] -> ([PASS][101], [PASS][102]) +2 similar issues
   [100]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-5/igt@gem_exec_fence@syncobj-wait.html
   [101]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-2/igt@gem_exec_fence@syncobj-wait.html
   [102]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-4/igt@gem_exec_fence@syncobj-wait.html

  * igt@gem_exec_schedule@submit-early-slice@bcs0:
    - {shard-tglu}:       [INCOMPLETE][103] ([i915#3797] / [i915#750]) -> [PASS][104]
   [103]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-tglu-7/igt@gem_exec_schedule@submit-early-slice@bcs0.html
   [104]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-tglu-5/igt@gem_exec_schedule@submit-early-slice@bcs0.html

  * igt@gem_exec_suspend@basic-s3@smem:
    - shard-apl:          [DMESG-WARN][105] ([i915#180]) -> [PASS][106]
   [105]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-apl3/igt@gem_exec_suspend@basic-s3@smem.html
   [106]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-apl6/igt@gem_exec_suspend@basic-s3@smem.html

  * igt@gem_exec_suspend@basic@smem:
    - {shard-tglu}:       [FAIL][107] ([i915#1888]) -> [PASS][108]
   [107]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-tglu-6/igt@gem_exec_suspend@basic@smem.html
   [108]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-tglu-8/igt@gem_exec_suspend@basic@smem.html

  * igt@gem_softpin@allocator-evict-all-engines:
    - shard-glk:          [DMESG-WARN][109] ([i915#118]) -> [PASS][110]
   [109]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-glk3/igt@gem_softpin@allocator-evict-all-engines.html
   [110]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-glk1/igt@gem_softpin@allocator-evict-all-engines.html

  * igt@gen9_exec_parse@allowed-all:
    - shard-skl:          [DMESG-WARN][111] ([i915#1436] / [i915#716]) -> [PASS][112]
   [111]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-skl4/igt@gen9_exec_parse@allowed-all.html
   [112]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl7/igt@gen9_exec_parse@allowed-all.html

  * igt@i915_pm_dc@dc6-psr:
    - shard-iclb:         [FAIL][113] ([i915#454]) -> [PASS][114]
   [113]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-iclb3/igt@i915_pm_dc@dc6-psr.html
   [114]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-iclb1/igt@i915_pm_dc@dc6-psr.html

  * igt@kms_ccs@pipe-a-bad-pixel-format-y_tiled_gen12_rc_ccs_cc:
    - {shard-rkl}:        [SKIP][115] ([i915#1845] / [i915#4098]) -> [PASS][116]
   [115]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-1/igt@kms_ccs@pipe-a-bad-pixel-format-y_tiled_gen12_rc_ccs_cc.html
   [116]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-6/igt@kms_ccs@pipe-a-bad-pixel-format-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_ccs@pipe-b-crc-primary-rotation-180-y_tiled_gen12_rc_ccs:
    - {shard-rkl}:        ([SKIP][117], [PASS][118]) ([i915#1845]) -> [PASS][119]
   [117]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-4/igt@kms_ccs@pipe-b-crc-primary-rotation-180-y_tiled_gen12_rc_ccs.html
   [118]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-6/igt@kms_ccs@pipe-b-crc-primary-rotation-180-y_tiled_gen12_rc_ccs.html
   [119]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-6/igt@kms_ccs@pipe-b-crc-primary-rotation-180-y_tiled_gen12_rc_ccs.html

  * igt@kms_cursor_crc@pipe-b-cursor-128x42-rapid-movement:
    - {shard-rkl}:        [SKIP][120] ([fdo#112022] / [i915#4070]) -> [PASS][121]
   [120]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-1/igt@kms_cursor_crc@pipe-b-cursor-128x42-rapid-movement.html
   [121]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-6/igt@kms_cursor_crc@pipe-b-cursor-128x42-rapid-movement.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size:
    - shard-skl:          [FAIL][122] ([i915#2346] / [i915#533]) -> [PASS][123]
   [122]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-skl7/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html
   [123]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-skl10/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html

  * igt@kms_cursor_legacy@flip-vs-cursor-toggle:
    - shard-iclb:         [FAIL][124] ([i915#2346]) -> [PASS][125]
   [124]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-iclb7/igt@kms_cursor_legacy@flip-vs-cursor-toggle.html
   [125]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-iclb8/igt@kms_cursor_legacy@flip-vs-cursor-toggle.html

  * igt@kms_draw_crc@draw-method-xrgb8888-pwrite-untiled:
    - {shard-rkl}:        [SKIP][126] ([fdo#111314]) -> [PASS][127] +1 similar issue
   [126]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-1/igt@kms_draw_crc@draw-method-xrgb8888-pwrite-untiled.html
   [127]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-6/igt@kms_draw_crc@draw-method-xrgb8888-pwrite-untiled.html

  * igt@kms_flip@flip-vs-expired-vblank-interruptible@a-dp1:
    - shard-kbl:          [FAIL][128] ([i915#79]) -> [PASS][129]
   [128]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-kbl7/igt@kms_flip@flip-vs-expired-vblank-interruptible@a-dp1.html
   [129]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-kbl7/igt@kms_flip@flip-vs-expired-vblank-interruptible@a-dp1.html

  * igt@kms_flip@flip-vs-suspend-interruptible@a-dp1:
    - shard-kbl:          [DMESG-WARN][130] ([i915#180]) -> [PASS][131] +12 similar issues
   [130]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-kbl4/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html
   [131]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-kbl3/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html

  * igt@kms_frontbuffer_tracking@fbc-rgb565-draw-render:
    - {shard-rkl}:        [SKIP][132] ([i915#1849]) -> [PASS][133] +1 similar issue
   [132]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-1/igt@kms_frontbuffer_tracking@fbc-rgb565-draw-render.html
   [133]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-6/igt@kms_frontbuffer_tracking@fbc-rgb565-draw-render.html

  * igt@kms_frontbuffer_tracking@psr-slowdraw:
    - {shard-rkl}:        ([SKIP][134], [SKIP][135]) ([i915#1849] / [i915#4098]) -> [PASS][136]
   [134]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-4/igt@kms_frontbuffer_tracking@psr-slowdraw.html
   [135]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-1/igt@kms_frontbuffer_tracking@psr-slowdraw.html
   [136]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-6/igt@kms_frontbuffer_tracking@psr-slowdraw.html

  * igt@kms_invalid_mode@uint-max-clock:
    - {shard-rkl}:        [SKIP][137] ([i915#4278]) -> [PASS][138]
   [137]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-1/igt@kms_invalid_mode@uint-max-clock.html
   [138]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-6/igt@kms_invalid_mode@uint-max-clock.html

  * igt@kms_plane_alpha_blend@pipe-a-constant-alpha-mid:
    - {shard-rkl}:        [SKIP][139] ([i915#1849] / [i915#4070]) -> [PASS][140] +1 similar issue
   [139]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-1/igt@kms_plane_alpha_blend@pipe-a-constant-alpha-mid.html
   [140]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-6/igt@kms_plane_alpha_blend@pipe-a-constant-alpha-mid.html

  * igt@kms_psr@psr2_cursor_render:
    - shard-iclb:         [SKIP][141] ([fdo#109441]) -> [PASS][142] +1 similar issue
   [141]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-iclb4/igt@kms_psr@psr2_cursor_render.html
   [142]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-iclb2/igt@kms_psr@psr2_cursor_render.html

  * igt@kms_psr@sprite_blt:
    - {shard-rkl}:        [SKIP][143] ([i915#1072]) -> [PASS][144]
   [143]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-1/igt@kms_psr@sprite_blt.html
   [144]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-6/igt@kms_psr@sprite_blt.html

  * igt@kms_pwrite_crc:
    - {shard-rkl}:        [SKIP][145] ([i915#1845]) -> [PASS][146] +3 similar issues
   [145]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-1/igt@kms_pwrite_crc.html
   [146]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-6/igt@kms_pwrite_crc.html

  * igt@kms_setmode@basic:
    - shard-apl:          [FAIL][147] ([i915#31]) -> [PASS][148]
   [147]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-apl1/igt@kms_setmode@basic.html
   [148]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-apl7/igt@kms_setmode@basic.html
    - shard-glk:          [FAIL][149] ([i915#31]) -> [PASS][150]
   [149]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-glk1/igt@kms_setmode@basic.html
   [150]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-glk5/igt@kms_setmode@basic.html

  * igt@kms_universal_plane@universal-plane-gen9-features-pipe-b:
    - {shard-rkl}:        [SKIP][151] ([i915#1845] / [i915#4070]) -> [PASS][152]
   [151]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11091/shard-rkl-1/igt@kms_universal_plane@universal-plane-gen9-features-pipe-b.html
   [152]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/shard-rkl-6/igt@kms_universal_plane@universal-plane-gen9-feat

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22007/index.html

[-- Attachment #2: Type: text/html, Size: 33158 bytes --]

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

* Re: [Intel-gfx] [PATCH v3 2/2] drm/i915/gt: make a gt sysfs group and move power management files
  2022-01-17 16:02   ` Tvrtko Ursulin
@ 2022-01-19  7:19       ` Joonas Lahtinen
  2022-01-19  7:19       ` Joonas Lahtinen
  1 sibling, 0 replies; 17+ messages in thread
From: Joonas Lahtinen @ 2022-01-19  7:19 UTC (permalink / raw)
  To: Andi Shyti, DRI Devel, Intel GFX, Tvrtko Ursulin
  Cc: Lucas De Marchi, Abdiel Janulgue, Matthew Auld

Quoting Tvrtko Ursulin (2022-01-17 18:02:50)
> 
> On 17/01/2022 15:09, Andi Shyti wrote:
> > The GT has its own properties and in sysfs they should be grouped
> > in the 'gt/' directory.
> > 
> > Create a 'gt/' directory in sysfs which will contain gt0...gtN
> > directories related to each tile configured in the GPU. Move the
> > power management files inside those directories.
> > 
> > The previous power management files are kept in their original
> > root directory to avoid breaking the ABI. They point to the tile
> > '0' and a warning message is printed whenever accessed to.

This is wrong. They should act as multiplexers to all the tiles.

Needs to be fixed before merging.

> > The
> > deprecated interface needs for the CONFIG_SYSFS_DEPRECATED_V2
> > flag in order to be generated.
> 
> CONFIG_SYSFS_DEPRECATED_V2 idea was abandoned, no? This patch at least 
> does not appear to contain it so please update the commit message to 
> reflect current state.
> 
> Adding Joonas to help address the question of how strict are userspace 
> requirements for sysfs additions. Personally sysadmin use sounds fine to 
> me, although it needs to be mentioned/documented as Matt requested, but 
> I fear it may not be enough to upstream. Is Level0 at the stage where we 
> can upstream for it I am also not sure.

Sysadmin usage is fine for the simple interfaces that can truly be used
from the command line. This patch seems to just expose the existing
interface in per-tile manner, so should not be a concern.

However, the controls not under gt directories, need to be converted to
apply to all tiles. (I've definitely given that feedback multiple
times). Otherwise it will be very unexpected to the end user when what
previously applied to whole device would only apply to part of it.

Regards, Joonas

> 
> While I am here I also left some nits below (not full review).
> 
> > 
> > The new sysfs structure will have a similar layout for the 4 tile
> > case:
> > 
> > /sys/.../card0
> >           \u251c\u2500\u2500 gt
> >           \u2502   \u251c\u2500\u2500 gt0
> >           \u2502   \u2502   \u251c\u2500\u2500 id
> >           \u2502   \u2502   \u251c\u2500\u2500 rc6_enable
> >           \u2502   \u2502   \u251c\u2500\u2500 rc6_residency_ms
> >           \u2502   \u2502   \u251c\u2500\u2500 rps_act_freq_mhz
> >           \u2502   \u2502   \u251c\u2500\u2500 rps_boost_freq_mhz
> >           \u2502   \u2502   \u251c\u2500\u2500 rps_cur_freq_mhz
> >           \u2502   \u2502   \u251c\u2500\u2500 rps_max_freq_mhz
> >           \u2502   \u2502   \u251c\u2500\u2500 rps_min_freq_mhz
> >           \u2502   \u2502   \u251c\u2500\u2500 rps_RP0_freq_mhz
> >           \u2502   \u2502   \u251c\u2500\u2500 rps_RP1_freq_mhz
> >           \u2502   \u2502   \u2514\u2500\u2500 rps_RPn_freq_mhz
> >        .   .
> >        .   .
> >        .   .
> >           \u2502   \u2514\u2500\u2500 gt3
> >           \u2502       \u251c\u2500\u2500 id
> >           \u2502       \u251c\u2500\u2500 rc6_enable
> >           \u2502       \u251c\u2500\u2500 rc6_residency_ms
> >           \u2502       \u251c\u2500\u2500 rps_act_freq_mhz
> >           \u2502       \u251c\u2500\u2500 rps_boost_freq_mhz
> >           \u2502       \u251c\u2500\u2500 rps_cur_freq_mhz
> >           \u2502       \u251c\u2500\u2500 rps_max_freq_mhz
> >           \u2502       \u251c\u2500\u2500 rps_min_freq_mhz
> >           \u2502       \u251c\u2500\u2500 rps_RP0_freq_mhz
> >           \u2502       \u251c\u2500\u2500 rps_RP1_freq_mhz
> >           \u2502       \u2514\u2500\u2500 rps_RPn_freq_mhz
> >           \u251c\u2500\u2500 gt_act_freq_mhz   -+
> >           \u251c\u2500\u2500 gt_boost_freq_mhz  |
> >           \u251c\u2500\u2500 gt_cur_freq_mhz    |    Original interface
> >           \u251c\u2500\u2500 gt_max_freq_mhz    +\u2500-> kept as existing ABI;
> >           \u251c\u2500\u2500 gt_min_freq_mhz    |    it points to gt0/
> >           \u251c\u2500\u2500 gt_RP0_freq_mhz    |
> >           \u2514\u2500\u2500 gt_RP1_freq_mhz    |
> >           \u2514\u2500\u2500 gt_RPn_freq_mhz   -+
> > 
> > As soon as multitile platforms will start being supported, this
> > interface will allow to control the power (either manually or
> > with tools) on each tile, instead of affecting only tile 0 and
> > getting incomplete results.
> > 
> > Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
> > Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
> > Cc: Matt Roper <matthew.d.roper@intel.com>
> > Cc: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
> > Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> > Reviewed-by: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
> > ---
> >   drivers/gpu/drm/i915/Makefile         |   4 +-
> >   drivers/gpu/drm/i915/gt/intel_gt.c    |   2 +
> >   drivers/gpu/drm/i915/gt/sysfs_gt.c    | 126 +++++++++
> >   drivers/gpu/drm/i915/gt/sysfs_gt.h    |  44 +++
> >   drivers/gpu/drm/i915/gt/sysfs_gt_pm.c | 393 ++++++++++++++++++++++++++
> >   drivers/gpu/drm/i915/gt/sysfs_gt_pm.h |  16 ++
> >   drivers/gpu/drm/i915/i915_drv.h       |   2 +
> >   drivers/gpu/drm/i915/i915_reg.h       |   1 +
> >   drivers/gpu/drm/i915/i915_sysfs.c     | 315 +--------------------
> >   drivers/gpu/drm/i915/i915_sysfs.h     |   3 +
> >   10 files changed, 600 insertions(+), 306 deletions(-)
> >   create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt.c
> >   create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt.h
> >   create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
> >   create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt_pm.h
> > 
> > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> > index aa86ac33effc..5fd203c626fc 100644
> > --- a/drivers/gpu/drm/i915/Makefile
> > +++ b/drivers/gpu/drm/i915/Makefile
> > @@ -121,7 +121,9 @@ gt-y += \
> >       gt/intel_timeline.o \
> >       gt/intel_workarounds.o \
> >       gt/shmem_utils.o \
> > -     gt/sysfs_engines.o
> > +     gt/sysfs_engines.o \
> > +     gt/sysfs_gt.o \
> > +     gt/sysfs_gt_pm.o
> >   # autogenerated null render state
> >   gt-y += \
> >       gt/gen6_renderstate.o \
> > diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
> > index 17927da9e23e..2584c51c1c14 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_gt.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_gt.c
> > @@ -25,6 +25,7 @@
> >   #include "intel_rps.h"
> >   #include "intel_uncore.h"
> >   #include "shmem_utils.h"
> > +#include "sysfs_gt.h"
> >   #include "pxp/intel_pxp.h"
> >   
> >   static void
> > @@ -453,6 +454,7 @@ void intel_gt_driver_register(struct intel_gt *gt)
> >       intel_rps_driver_register(&gt->rps);
> >   
> >       intel_gt_debugfs_register(gt);
> > +     intel_gt_sysfs_register(gt);
> >   }
> >   
> >   static int intel_gt_init_scratch(struct intel_gt *gt, unsigned int size)
> > diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt.c b/drivers/gpu/drm/i915/gt/sysfs_gt.c
> > new file mode 100644
> > index 000000000000..46cf033a53ec
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/gt/sysfs_gt.c
> > @@ -0,0 +1,126 @@
> > +// SPDX-License-Identifier: MIT
> > +/*
> > + * Copyright © 2020 Intel Corporation
> > + */
> > +
> > +#include <drm/drm_device.h>
> > +#include <linux/device.h>
> > +#include <linux/kobject.h>
> > +#include <linux/printk.h>
> > +#include <linux/sysfs.h>
> > +
> > +#include "i915_drv.h"
> > +#include "i915_sysfs.h"
> > +#include "intel_gt.h"
> > +#include "intel_gt_types.h"
> > +#include "intel_rc6.h"
> > +
> > +#include "sysfs_gt.h"
> > +#include "sysfs_gt_pm.h"
> > +
> > +struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
> > +                                         const char *name)
> > +{
> > +     struct kobject *kobj = &dev->kobj;
> > +
> > +     /*
> > +      * We are interested at knowing from where the interface
> > +      * has been called, whether it's called from gt/ or from
> > +      * the parent directory.
> > +      * From the interface position it depends also the value of
> > +      * the private data.
> > +      * If the interface is called from gt/ then private data is
> > +      * of the "struct intel_gt *" type, otherwise it's * a
> > +      * "struct drm_i915_private *" type.
> > +      */
> > +     if (!is_object_gt(kobj)) {
> > +             struct drm_i915_private *i915 = kdev_minor_to_i915(dev);
> > +
> > +             pr_devel_ratelimited(DEPRECATED
> > +                     "%s (pid %d) is trying to access deprecated %s "
> > +                     "sysfs control, please use gt/gt<n>/%s instead\n",
> 
> Maybe reword "is trying to access" to "is accesing" to remove any doubt 
> whether something is failing or not?
> 
> > +                     current->comm, task_pid_nr(current), name, name);
> > +             return to_gt(i915);
> > +     }
> > +
> > +     return kobj_to_gt(kobj);
> > +}
> > +
> > +static struct kobject *gt_get_parent_obj(struct intel_gt *gt)
> > +{
> > +     return &gt->i915->drm.primary->kdev->kobj;
> > +}
> > +
> > +static ssize_t id_show(struct device *dev,
> > +                    struct device_attribute *attr,
> > +                    char *buf)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +
> > +     return sysfs_emit(buf, "%u\n", gt->info.id);
> > +}
> > +
> > +static DEVICE_ATTR_RO(id);
> > +
> > +static void kobj_gt_release(struct kobject *kobj)
> > +{
> > +     kfree(kobj);
> > +}
> > +
> > +static struct kobj_type kobj_gt_type = {
> > +     .release = kobj_gt_release,
> > +     .sysfs_ops = &kobj_sysfs_ops
> > +};
> > +
> > +struct kobject *
> > +intel_gt_create_kobj(struct intel_gt *gt, struct kobject *dir, const char *name)
> > +{
> > +     struct kobj_gt *kg;
> > +
> > +     kg = kzalloc(sizeof(*kg), GFP_KERNEL);
> > +     if (!kg)
> > +             return NULL;
> > +
> > +     kobject_init(&kg->base, &kobj_gt_type);
> > +     kg->gt = gt;
> > +
> > +     /* xfer ownership to sysfs tree */
> > +     if (kobject_add(&kg->base, dir, "%s", name)) {
> > +             kobject_put(&kg->base);
> > +             return NULL;
> > +     }
> > +
> > +     return &kg->base; /* borrowed ref */
> > +}
> > +
> > +void intel_gt_sysfs_register(struct intel_gt *gt)
> > +{
> > +     struct kobject *dir;
> > +     char name[80];
> > +
> > +     /*
> > +      * We need to make things right with the
> > +      * ABI compatibility. The files were originally
> > +      * generated under the parent directory.
> > +      *
> > +      * We generate the files only for gt 0
> > +      * to avoid duplicates.
> > +      */
> > +     if (!gt->info.id)
> > +             intel_gt_sysfs_pm_init(gt, gt_get_parent_obj(gt));
> > +
> > +     snprintf(name, sizeof(name), "gt%d", gt->info.id);
> > +
> > +     dir = intel_gt_create_kobj(gt, gt->i915->sysfs_gt, name);
> > +     if (!dir) {
> > +             drm_err(&gt->i915->drm,
> > +                     "failed to initialize %s sysfs root\n", name);
> > +             return;
> > +     }
> > +
> > +     if (sysfs_create_file(dir, &dev_attr_id.attr))
> > +             drm_err(&gt->i915->drm,
> > +                     "failed to create sysfs %s info files\n", name);
> 
> These drm_err could maybe be warn or notice, to reflect the fact driver 
> is most likely completely functional? But only maybe since I haven't 
> checked what we do for other sysfs failures. If rest are drm_err then I 
> guess consistency trumps it.
> 
> > +
> > +     intel_gt_sysfs_pm_init(gt, dir);
> > +}
> > diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt.h b/drivers/gpu/drm/i915/gt/sysfs_gt.h
> > new file mode 100644
> > index 000000000000..cd80a14bb14d
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/gt/sysfs_gt.h
> > @@ -0,0 +1,44 @@
> > +/* SPDX-License-Identifier: MIT */
> > +/*
> > + * Copyright © 2020 Intel Corporation
> > + */
> > +
> > +#ifndef __SYSFS_GT_H__
> > +#define __SYSFS_GT_H__
> > +
> > +#include <linux/ctype.h>
> > +#include <linux/kobject.h>
> > +
> > +#include "i915_gem.h" /* GEM_BUG_ON() */
> > +
> > +struct intel_gt;
> > +
> > +struct kobj_gt {
> > +     struct kobject base;
> > +     struct intel_gt *gt;
> > +};
> > +
> > +static inline bool is_object_gt(struct kobject *kobj)
> > +{
> > +     bool b = !strncmp(kobj->name, "gt", 2);
> > +
> > +     GEM_BUG_ON(b && !isdigit(kobj->name[2]));
> 
> 1)
> Not sure what is the point of this GEM_BUG_ON? Checking strncmp works 
> feels like an overkill.
> 
> 2)
> With the recent trend of "static inline considered harmful" perhaps 
> consider moving it out of line.
> 
> > +
> > +     return b;
> > +}
> > +
> > +struct kobject *
> > +intel_gt_create_kobj(struct intel_gt *gt,
> > +                  struct kobject *dir,
> > +                  const char *name);
> > +
> > +static inline struct intel_gt *kobj_to_gt(struct kobject *kobj)
> > +{
> > +     return container_of(kobj, struct kobj_gt, base)->gt;
> > +}
> > +
> > +void intel_gt_sysfs_register(struct intel_gt *gt);
> > +struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
> > +                                         const char *name);
> > +
> > +#endif /* SYSFS_GT_H */
> > diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt_pm.c b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
> > new file mode 100644
> > index 000000000000..6f4424be42d1
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
> > @@ -0,0 +1,393 @@
> > +// SPDX-License-Identifier: MIT
> > +/*
> > + * Copyright © 2020 Intel Corporation
> > + */
> > +
> > +#include <drm/drm_device.h>
> > +#include <linux/sysfs.h>
> > +#include <linux/printk.h>
> > +
> > +#include "i915_drv.h"
> > +#include "intel_gt.h"
> > +#include "intel_rc6.h"
> > +#include "intel_rps.h"
> > +#include "sysfs_gt.h"
> > +#include "sysfs_gt_pm.h"
> > +
> > +#ifdef CONFIG_PM
> > +static u32 get_residency(struct intel_gt *gt, i915_reg_t reg)
> > +{
> > +     intel_wakeref_t wakeref;
> > +     u64 res = 0;
> > +
> > +     with_intel_runtime_pm(gt->uncore->rpm, wakeref)
> > +             res = intel_rc6_residency_us(&gt->rc6, reg);
> > +
> > +     return DIV_ROUND_CLOSEST_ULL(res, 1000);
> > +}
> > +
> > +static ssize_t rc6_enable_show(struct device *dev,
> > +                            struct device_attribute *attr,
> > +                            char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     u8 mask = 0;
> > +
> > +     if (HAS_RC6(gt->i915))
> > +             mask |= BIT(0);
> > +     if (HAS_RC6p(gt->i915))
> > +             mask |= BIT(1);
> > +     if (HAS_RC6pp(gt->i915))
> > +             mask |= BIT(2);
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%x\n", mask);
> > +}
> > +
> > +static ssize_t rc6_residency_ms_show(struct device *dev,
> > +                                  struct device_attribute *attr,
> > +                                  char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     u32 rc6_residency = get_residency(gt, GEN6_GT_GFX_RC6);
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%u\n", rc6_residency);
> > +}
> > +
> > +static ssize_t rc6p_residency_ms_show(struct device *dev,
> > +                                   struct device_attribute *attr,
> > +                                   char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     u32 rc6p_residency = get_residency(gt, GEN6_GT_GFX_RC6p);
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%u\n", rc6p_residency);
> > +}
> > +
> > +static ssize_t rc6pp_residency_ms_show(struct device *dev,
> > +                                    struct device_attribute *attr,
> > +                                    char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     u32 rc6pp_residency = get_residency(gt, GEN6_GT_GFX_RC6pp);
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%u\n", rc6pp_residency);
> > +}
> > +
> > +static ssize_t media_rc6_residency_ms_show(struct device *dev,
> > +                                        struct device_attribute *attr,
> > +                                        char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     u32 rc6_residency = get_residency(gt, VLV_GT_MEDIA_RC6);
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%u\n", rc6_residency);
> > +}
> > +
> > +static DEVICE_ATTR_RO(rc6_enable);
> > +static DEVICE_ATTR_RO(rc6_residency_ms);
> > +static DEVICE_ATTR_RO(rc6p_residency_ms);
> > +static DEVICE_ATTR_RO(rc6pp_residency_ms);
> > +static DEVICE_ATTR_RO(media_rc6_residency_ms);
> > +
> > +static struct attribute *rc6_attrs[] = {
> > +     &dev_attr_rc6_enable.attr,
> > +     &dev_attr_rc6_residency_ms.attr,
> > +     NULL
> > +};
> > +
> > +static struct attribute *rc6p_attrs[] = {
> > +     &dev_attr_rc6p_residency_ms.attr,
> > +     &dev_attr_rc6pp_residency_ms.attr,
> > +     NULL
> > +};
> > +
> > +static struct attribute *media_rc6_attrs[] = {
> > +     &dev_attr_media_rc6_residency_ms.attr,
> > +     NULL
> > +};
> > +
> > +static const struct attribute_group rc6_attr_group[] = {
> > +     { .name = power_group_name, .attrs = rc6_attrs },
> > +     { .attrs = rc6_attrs }
> > +};
> > +
> > +static const struct attribute_group rc6p_attr_group[] = {
> > +     { .name = power_group_name, .attrs = rc6p_attrs },
> > +     { .attrs = rc6p_attrs }
> > +};
> > +
> > +static const struct attribute_group media_rc6_attr_group[] = {
> > +     { .name = power_group_name, .attrs = media_rc6_attrs },
> > +     { .attrs = media_rc6_attrs }
> > +};
> > +
> > +static int __intel_gt_sysfs_create_group(struct kobject *kobj,
> > +                                      const struct attribute_group *grp)
> > +{
> > +     int i = is_object_gt(kobj);
> 
> Is_object_gt returns a bool so can I be pedantic? :) Maybe just omit the 
> local and solve it like that.
> 
> > +
> > +     return i ? sysfs_create_group(kobj, &grp[i]) :
> > +                sysfs_merge_group(kobj, &grp[i]);
> > +}
> > +
> > +static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj)
> > +{
> > +     int ret;
> > +
> > +     if (!HAS_RC6(gt->i915))
> > +             return;
> > +
> > +     ret = __intel_gt_sysfs_create_group(kobj, rc6_attr_group);
> > +     if (ret)
> > +             drm_err(&gt->i915->drm,
> > +                     "failed to create gt%u RC6 sysfs files\n", gt->info.id);
> > +
> > +     if (HAS_RC6p(gt->i915)) {
> > +             ret = __intel_gt_sysfs_create_group(kobj, rc6p_attr_group);
> > +             if (ret)
> > +                     drm_err(&gt->i915->drm,
> > +                             "failed to create gt%u RC6p sysfs files\n",
> > +                             gt->info.id);
> > +     }
> > +
> > +     if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915)) {
> > +             ret = __intel_gt_sysfs_create_group(kobj, media_rc6_attr_group);
> > +             if (ret)
> > +                     drm_err(&gt->i915->drm,
> > +                             "failed to create media %u RC6 sysfs files\n",
> > +                             gt->info.id);
> > +     }
> > +}
> > +#else
> > +static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj)
> > +{
> > +}
> > +#endif /* CONFIG_PM */
> > +
> > +static ssize_t act_freq_mhz_show(struct device *dev,
> > +                              struct device_attribute *attr, char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%d\n",
> > +                     intel_rps_read_actual_frequency(&gt->rps));
> > +}
> > +
> > +static ssize_t cur_freq_mhz_show(struct device *dev,
> > +                              struct device_attribute *attr, char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%d\n",
> > +                      intel_rps_get_requested_frequency(rps));
> > +}
> > +
> > +static ssize_t boost_freq_mhz_show(struct device *dev,
> > +                                struct device_attribute *attr,
> > +                                char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%d\n",
> > +                      intel_rps_get_boost_frequency(rps));
> > +}
> > +
> > +static ssize_t boost_freq_mhz_store(struct device *dev,
> > +                                 struct device_attribute *attr,
> > +                                 const char *buff, size_t count)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +     bool boost = false;
> > +     ssize_t ret;
> > +     u32 val;
> > +
> > +     ret = kstrtou32(buff, 0, &val);
> > +     if (ret)
> > +             return ret;
> > +
> > +     /* Validate against (static) hardware limits */
> > +     val = intel_freq_opcode(rps, val);
> > +     if (val < rps->min_freq || val > rps->max_freq)
> > +             return -EINVAL;
> > +
> > +     mutex_lock(&rps->lock);
> > +     if (val != rps->boost_freq) {
> > +             rps->boost_freq = val;
> > +             boost = atomic_read(&rps->num_waiters);
> > +     }
> > +     mutex_unlock(&rps->lock);
> > +     if (boost)
> > +             schedule_work(&rps->work);
> > +
> > +     return count;
> > +}
> > +
> > +static ssize_t vlv_rpe_freq_mhz_show(struct device *dev,
> > +                                  struct device_attribute *attr, char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%d\n",
> > +                     intel_gpu_freq(rps, rps->efficient_freq));
> > +}
> > +
> > +static ssize_t max_freq_mhz_show(struct device *dev,
> > +                              struct device_attribute *attr,
> > +                              char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +
> > +     return sysfs_emit(buff, "%d\n", intel_rps_get_max_frequency(rps));
> > +}
> > +
> > +static ssize_t max_freq_mhz_store(struct device *dev,
> > +                               struct device_attribute *attr,
> > +                               const char *buff, size_t count)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +     ssize_t ret;
> > +     u32 val;
> > +
> > +     ret = kstrtou32(buff, 0, &val);
> > +     if (ret)
> > +             return ret;
> > +
> > +     ret = intel_rps_set_max_frequency(rps, val);
> > +
> > +     return ret ?: count;
> > +}
> > +
> > +static ssize_t min_freq_mhz_show(struct device *dev,
> > +                              struct device_attribute *attr,
> > +                              char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +
> > +     return sysfs_emit(buff, "%d\n", intel_rps_get_min_frequency(rps));
> > +}
> > +
> > +static ssize_t min_freq_mhz_store(struct device *dev,
> > +                               struct device_attribute *attr,
> > +                               const char *buff, size_t count)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +     ssize_t ret;
> > +     u32 val;
> > +
> > +     ret = kstrtou32(buff, 0, &val);
> > +     if (ret)
> > +             return ret;
> > +
> > +     ret = intel_rps_set_min_frequency(rps, val);
> > +
> > +     return ret ?: count;
> > +}
> > +
> > +#define INTEL_GT_RPS_SYSFS_ATTR(_name, _mode, _show, _store) \
> > +     struct device_attribute dev_attr_gt_##_name = __ATTR(gt_##_name, _mode, _show, _store); \
> > +     struct device_attribute dev_attr_rps_##_name = __ATTR(rps_##_name, _mode, _show, _store)
> > +
> > +#define INTEL_GT_RPS_SYSFS_ATTR_RO(_name)                            \
> > +             INTEL_GT_RPS_SYSFS_ATTR(_name, 0444, _name##_show, NULL)
> > +#define INTEL_GT_RPS_SYSFS_ATTR_RW(_name)                            \
> > +             INTEL_GT_RPS_SYSFS_ATTR(_name, 0644, _name##_show, _name##_store)
> > +
> > +static INTEL_GT_RPS_SYSFS_ATTR_RO(act_freq_mhz);
> > +static INTEL_GT_RPS_SYSFS_ATTR_RO(cur_freq_mhz);
> > +static INTEL_GT_RPS_SYSFS_ATTR_RW(boost_freq_mhz);
> > +static INTEL_GT_RPS_SYSFS_ATTR_RW(max_freq_mhz);
> > +static INTEL_GT_RPS_SYSFS_ATTR_RW(min_freq_mhz);
> > +
> > +static DEVICE_ATTR_RO(vlv_rpe_freq_mhz);
> > +
> > +static ssize_t rps_rp_mhz_show(struct device *dev,
> > +                            struct device_attribute *attr,
> > +                            char *buff);
> > +
> > +static INTEL_GT_RPS_SYSFS_ATTR(RP0_freq_mhz, 0444, rps_rp_mhz_show, NULL);
> > +static INTEL_GT_RPS_SYSFS_ATTR(RP1_freq_mhz, 0444, rps_rp_mhz_show, NULL);
> > +static INTEL_GT_RPS_SYSFS_ATTR(RPn_freq_mhz, 0444, rps_rp_mhz_show, NULL);
> > +
> > +#define GEN6_ATTR(s) { \
> > +             &dev_attr_##s##_act_freq_mhz.attr, \
> > +             &dev_attr_##s##_cur_freq_mhz.attr, \
> > +             &dev_attr_##s##_boost_freq_mhz.attr, \
> > +             &dev_attr_##s##_max_freq_mhz.attr, \
> > +             &dev_attr_##s##_min_freq_mhz.attr, \
> > +             &dev_attr_##s##_RP0_freq_mhz.attr, \
> > +             &dev_attr_##s##_RP1_freq_mhz.attr, \
> > +             &dev_attr_##s##_RPn_freq_mhz.attr, \
> > +             NULL, \
> > +     }
> > +
> > +#define GEN6_RPS_ATTR GEN6_ATTR(rps)
> > +#define GEN6_GT_ATTR  GEN6_ATTR(gt)
> > +
> > +/* For now we have a static number of RP states */
> > +static ssize_t rps_rp_mhz_show(struct device *dev,
> > +                            struct device_attribute *attr,
> > +                            char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +     u32 val;
> > +
> > +     if (attr == &dev_attr_gt_RP0_freq_mhz ||
> > +         attr == &dev_attr_rps_RP0_freq_mhz) {
> > +             val = intel_rps_get_rp0_frequency(rps);
> > +     } else if (attr == &dev_attr_gt_RP1_freq_mhz ||
> > +                attr == &dev_attr_rps_RP1_freq_mhz) {
> > +                val = intel_rps_get_rp1_frequency(rps);
> > +     } else if (attr == &dev_attr_gt_RPn_freq_mhz ||
> > +                attr == &dev_attr_rps_RPn_freq_mhz) {
> > +                val = intel_rps_get_rpn_frequency(rps);
> > +     } else {
> > +             GEM_WARN_ON(1);
> > +             return -ENODEV;
> > +     }
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%d\n", val);
> > +}
> > +
> > +static const struct attribute * const gen6_rps_attrs[] = GEN6_RPS_ATTR;
> > +static const struct attribute * const gen6_gt_attrs[]  = GEN6_GT_ATTR;
> > +
> > +static int intel_sysfs_rps_init(struct intel_gt *gt, struct kobject *kobj,
> > +                             const struct attribute * const *attrs)
> > +{
> > +     int ret;
> > +
> > +     if (GRAPHICS_VER(gt->i915) < 6)
> > +             return 0;
> > +
> > +     ret = sysfs_create_files(kobj, attrs);
> > +     if (ret)
> > +             return ret;
> > +
> > +     if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915))
> > +             ret = sysfs_create_file(kobj, &dev_attr_vlv_rpe_freq_mhz.attr);
> > +
> > +     return ret;
> > +}
> > +
> > +void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj)
> > +{
> > +     int ret;
> > +
> > +     intel_sysfs_rc6_init(gt, kobj);
> > +
> > +     ret = is_object_gt(kobj) ?
> > +           intel_sysfs_rps_init(gt, kobj, gen6_rps_attrs) :
> > +           intel_sysfs_rps_init(gt, kobj, gen6_gt_attrs);
> > +     if (ret)
> > +             drm_err(&gt->i915->drm,
> > +                     "failed to create gt%u RPS sysfs files", gt->info.id);
> > +}
> > diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt_pm.h b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.h
> > new file mode 100644
> > index 000000000000..18c60d929e6d
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.h
> > @@ -0,0 +1,16 @@
> > +/* SPDX-License-Identifier: MIT */
> > +/*
> > + * Copyright © 2020 Intel Corporation
> > + */
> > +
> > +#ifndef __SYSFS_GT_PM_H__
> > +#define __SYSFS_GT_PM_H__
> > +
> > +#include <linux/kobject.h>
> > +
> > +#include "intel_gt_types.h"
> > +
> > +void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj);
> > +void intel_gt_sysfs_pm_remove(struct intel_gt *gt, struct kobject *kobj);
> > +
> > +#endif /* SYSFS_RC6_H */
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index ec76011366fb..f11acbc0990b 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -989,6 +989,8 @@ struct drm_i915_private {
> >   #define I915_MAX_GT 4
> >       struct intel_gt *gt[I915_MAX_GT];
> >   
> > +     struct kobject *sysfs_gt;
> > +
> >       struct {
> >               struct i915_gem_contexts {
> >                       spinlock_t lock; /* locks list */
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index ef6bc8180073..5153b3ff41e9 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -8480,6 +8480,7 @@ enum {
> >   #define   GEN6_AGGRESSIVE_TURBO                     (0 << 15)
> >   #define   GEN9_SW_REQ_UNSLICE_RATIO_SHIFT   23
> >   #define   GEN9_IGNORE_SLICE_RATIO           (0 << 0)
> > +#define   GEN12_SW_REQ_UNSLICE_RATIO_SHIFT   23
> 
> Stray something?
> 
> >   
> >   #define GEN6_RC_VIDEO_FREQ                  _MMIO(0xA00C)
> >   #define GEN6_RC_CONTROL                             _MMIO(0xA090)
> > diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
> > index fae4d1f4f275..d6687e33f29d 100644
> > --- a/drivers/gpu/drm/i915/i915_sysfs.c
> > +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> > @@ -38,113 +38,12 @@
> >   #include "i915_sysfs.h"
> >   #include "intel_pm.h"
> >   
> > -static inline struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
> > +struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
> >   {
> >       struct drm_minor *minor = dev_get_drvdata(kdev);
> >       return to_i915(minor->dev);
> >   }
> >   
> > -#ifdef CONFIG_PM
> > -static u32 calc_residency(struct drm_i915_private *dev_priv,
> > -                       i915_reg_t reg)
> > -{
> > -     intel_wakeref_t wakeref;
> > -     u64 res = 0;
> > -
> > -     with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref)
> > -             res = intel_rc6_residency_us(&to_gt(dev_priv)->rc6, reg);
> > -
> > -     return DIV_ROUND_CLOSEST_ULL(res, 1000);
> > -}
> > -
> > -static ssize_t rc6_enable_show(struct device *kdev,
> > -                            struct device_attribute *attr, char *buf)
> > -{
> > -     struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> > -     unsigned int mask;
> > -
> > -     mask = 0;
> > -     if (HAS_RC6(dev_priv))
> > -             mask |= BIT(0);
> > -     if (HAS_RC6p(dev_priv))
> > -             mask |= BIT(1);
> > -     if (HAS_RC6pp(dev_priv))
> > -             mask |= BIT(2);
> > -
> > -     return sysfs_emit(buf, "%x\n", mask);
> > -}
> > -
> > -static ssize_t rc6_residency_ms_show(struct device *kdev,
> > -                                  struct device_attribute *attr, char *buf)
> > -{
> > -     struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> > -     u32 rc6_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6);
> > -     return sysfs_emit(buf, "%u\n", rc6_residency);
> > -}
> > -
> > -static ssize_t rc6p_residency_ms_show(struct device *kdev,
> > -                                   struct device_attribute *attr, char *buf)
> > -{
> > -     struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> > -     u32 rc6p_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6p);
> > -     return sysfs_emit(buf, "%u\n", rc6p_residency);
> > -}
> > -
> > -static ssize_t rc6pp_residency_ms_show(struct device *kdev,
> > -                                    struct device_attribute *attr, char *buf)
> > -{
> > -     struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> > -     u32 rc6pp_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6pp);
> > -     return sysfs_emit(buf, "%u\n", rc6pp_residency);
> > -}
> > -
> > -static ssize_t media_rc6_residency_ms_show(struct device *kdev,
> > -                                        struct device_attribute *attr, char *buf)
> > -{
> > -     struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> > -     u32 rc6_residency = calc_residency(dev_priv, VLV_GT_MEDIA_RC6);
> > -     return sysfs_emit(buf, "%u\n", rc6_residency);
> > -}
> > -
> > -static DEVICE_ATTR_RO(rc6_enable);
> > -static DEVICE_ATTR_RO(rc6_residency_ms);
> > -static DEVICE_ATTR_RO(rc6p_residency_ms);
> > -static DEVICE_ATTR_RO(rc6pp_residency_ms);
> > -static DEVICE_ATTR_RO(media_rc6_residency_ms);
> > -
> > -static struct attribute *rc6_attrs[] = {
> > -     &dev_attr_rc6_enable.attr,
> > -     &dev_attr_rc6_residency_ms.attr,
> > -     NULL
> > -};
> > -
> > -static const struct attribute_group rc6_attr_group = {
> > -     .name = power_group_name,
> > -     .attrs =  rc6_attrs
> > -};
> > -
> > -static struct attribute *rc6p_attrs[] = {
> > -     &dev_attr_rc6p_residency_ms.attr,
> > -     &dev_attr_rc6pp_residency_ms.attr,
> > -     NULL
> > -};
> > -
> > -static const struct attribute_group rc6p_attr_group = {
> > -     .name = power_group_name,
> > -     .attrs =  rc6p_attrs
> > -};
> > -
> > -static struct attribute *media_rc6_attrs[] = {
> > -     &dev_attr_media_rc6_residency_ms.attr,
> > -     NULL
> > -};
> > -
> > -static const struct attribute_group media_rc6_attr_group = {
> > -     .name = power_group_name,
> > -     .attrs =  media_rc6_attrs
> > -};
> > -#endif
> > -
> >   static int l3_access_valid(struct drm_i915_private *i915, loff_t offset)
> >   {
> >       if (!HAS_L3_DPF(i915))
> > @@ -256,171 +155,6 @@ static const struct bin_attribute dpf_attrs_1 = {
> >       .private = (void *)1
> >   };
> >   
> > -static ssize_t gt_act_freq_mhz_show(struct device *kdev,
> > -                                 struct device_attribute *attr, char *buf)
> > -{
> > -     struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
> > -     struct intel_rps *rps = &to_gt(i915)->rps;
> > -
> > -     return sysfs_emit(buf, "%d\n", intel_rps_read_actual_frequency(rps));
> > -}
> > -
> > -static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
> > -                                 struct device_attribute *attr, char *buf)
> > -{
> > -     struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
> > -     struct intel_rps *rps = &to_gt(i915)->rps;
> > -
> > -     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)
> > -{
> > -     struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
> > -     struct intel_rps *rps = &to_gt(i915)->rps;
> > -
> > -     return sysfs_emit(buf, "%d\n", intel_rps_get_boost_frequency(rps));
> > -}
> > -
> > -static ssize_t gt_boost_freq_mhz_store(struct device *kdev,
> > -                                    struct device_attribute *attr,
> > -                                    const char *buf, size_t count)
> > -{
> > -     struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> > -     struct intel_rps *rps = &to_gt(dev_priv)->rps;
> > -     ssize_t ret;
> > -     u32 val;
> > -
> > -     ret = kstrtou32(buf, 0, &val);
> > -     if (ret)
> > -             return ret;
> > -
> > -     ret = intel_rps_set_boost_frequency(rps, val);
> > -
> > -     return ret ?: count;
> > -}
> > -
> > -static ssize_t vlv_rpe_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 = &to_gt(dev_priv)->rps;
> > -
> > -     return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->efficient_freq));
> > -}
> > -
> > -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_gt *gt = to_gt(dev_priv);
> > -     struct intel_rps *rps = &gt->rps;
> > -
> > -     return sysfs_emit(buf, "%d\n", intel_rps_get_max_frequency(rps));
> > -}
> > -
> > -static ssize_t gt_max_freq_mhz_store(struct device *kdev,
> > -                                  struct device_attribute *attr,
> > -                                  const char *buf, size_t count)
> > -{
> > -     struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> > -     struct intel_gt *gt = to_gt(dev_priv);
> > -     struct intel_rps *rps = &gt->rps;
> > -     ssize_t ret;
> > -     u32 val;
> > -
> > -     ret = kstrtou32(buf, 0, &val);
> > -     if (ret)
> > -             return ret;
> > -
> > -     ret = intel_rps_set_max_frequency(rps, val);
> > -
> > -     return ret ?: count;
> > -}
> > -
> > -static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
> > -{
> > -     struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
> > -     struct intel_gt *gt = to_gt(i915);
> > -     struct intel_rps *rps = &gt->rps;
> > -
> > -     return sysfs_emit(buf, "%d\n", intel_rps_get_min_frequency(rps));
> > -}
> > -
> > -static ssize_t gt_min_freq_mhz_store(struct device *kdev,
> > -                                  struct device_attribute *attr,
> > -                                  const char *buf, size_t count)
> > -{
> > -     struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
> > -     struct intel_rps *rps = &to_gt(i915)->rps;
> > -     ssize_t ret;
> > -     u32 val;
> > -
> > -     ret = kstrtou32(buf, 0, &val);
> > -     if (ret)
> > -             return ret;
> > -
> > -     ret = intel_rps_set_min_frequency(rps, val);
> > -
> > -     return ret ?: count;
> > -}
> > -
> > -static DEVICE_ATTR_RO(gt_act_freq_mhz);
> > -static DEVICE_ATTR_RO(gt_cur_freq_mhz);
> > -static DEVICE_ATTR_RW(gt_boost_freq_mhz);
> > -static DEVICE_ATTR_RW(gt_max_freq_mhz);
> > -static DEVICE_ATTR_RW(gt_min_freq_mhz);
> > -
> > -static DEVICE_ATTR_RO(vlv_rpe_freq_mhz);
> > -
> > -static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf);
> > -static DEVICE_ATTR(gt_RP0_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
> > -static DEVICE_ATTR(gt_RP1_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
> > -static DEVICE_ATTR(gt_RPn_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
> > -
> > -/* For now we have a static number of RP states */
> > -static ssize_t gt_rp_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 = &to_gt(dev_priv)->rps;
> > -     u32 val;
> > -
> > -     if (attr == &dev_attr_gt_RP0_freq_mhz)
> > -             val = intel_rps_get_rp0_frequency(rps);
> > -     else if (attr == &dev_attr_gt_RP1_freq_mhz)
> > -             val = intel_rps_get_rp1_frequency(rps);
> > -     else if (attr == &dev_attr_gt_RPn_freq_mhz)
> > -             val = intel_rps_get_rpn_frequency(rps);
> > -     else
> > -             BUG();
> > -
> > -     return sysfs_emit(buf, "%d\n", val);
> > -}
> > -
> > -static const struct attribute * const gen6_attrs[] = {
> > -     &dev_attr_gt_act_freq_mhz.attr,
> > -     &dev_attr_gt_cur_freq_mhz.attr,
> > -     &dev_attr_gt_boost_freq_mhz.attr,
> > -     &dev_attr_gt_max_freq_mhz.attr,
> > -     &dev_attr_gt_min_freq_mhz.attr,
> > -     &dev_attr_gt_RP0_freq_mhz.attr,
> > -     &dev_attr_gt_RP1_freq_mhz.attr,
> > -     &dev_attr_gt_RPn_freq_mhz.attr,
> > -     NULL,
> > -};
> > -
> > -static const struct attribute * const vlv_attrs[] = {
> > -     &dev_attr_gt_act_freq_mhz.attr,
> > -     &dev_attr_gt_cur_freq_mhz.attr,
> > -     &dev_attr_gt_boost_freq_mhz.attr,
> > -     &dev_attr_gt_max_freq_mhz.attr,
> > -     &dev_attr_gt_min_freq_mhz.attr,
> > -     &dev_attr_gt_RP0_freq_mhz.attr,
> > -     &dev_attr_gt_RP1_freq_mhz.attr,
> > -     &dev_attr_gt_RPn_freq_mhz.attr,
> > -     &dev_attr_vlv_rpe_freq_mhz.attr,
> > -     NULL,
> > -};
> > -
> >   #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
> >   
> >   static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
> > @@ -486,34 +220,16 @@ static void i915_setup_error_capture(struct device *kdev) {}
> >   static void i915_teardown_error_capture(struct device *kdev) {}
> >   #endif
> >   
> > +static struct kobject *i915_setup_gt_sysfs(struct kobject *parent)
> > +{
> > +     return kobject_create_and_add("gt", parent);
> > +}
> > +
> >   void i915_setup_sysfs(struct drm_i915_private *dev_priv)
> >   {
> >       struct device *kdev = dev_priv->drm.primary->kdev;
> >       int ret;
> >   
> > -#ifdef CONFIG_PM
> > -     if (HAS_RC6(dev_priv)) {
> > -             ret = sysfs_merge_group(&kdev->kobj,
> > -                                     &rc6_attr_group);
> > -             if (ret)
> > -                     drm_err(&dev_priv->drm,
> > -                             "RC6 residency sysfs setup failed\n");
> > -     }
> > -     if (HAS_RC6p(dev_priv)) {
> > -             ret = sysfs_merge_group(&kdev->kobj,
> > -                                     &rc6p_attr_group);
> > -             if (ret)
> > -                     drm_err(&dev_priv->drm,
> > -                             "RC6p residency sysfs setup failed\n");
> > -     }
> > -     if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> > -             ret = sysfs_merge_group(&kdev->kobj,
> > -                                     &media_rc6_attr_group);
> > -             if (ret)
> > -                     drm_err(&dev_priv->drm,
> > -                             "Media RC6 residency sysfs setup failed\n");
> > -     }
> > -#endif
> >       if (HAS_L3_DPF(dev_priv)) {
> >               ret = device_create_bin_file(kdev, &dpf_attrs);
> >               if (ret)
> > @@ -529,13 +245,10 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv)
> >               }
> >       }
> >   
> > -     ret = 0;
> > -     if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> > -             ret = sysfs_create_files(&kdev->kobj, vlv_attrs);
> > -     else if (GRAPHICS_VER(dev_priv) >= 6)
> > -             ret = sysfs_create_files(&kdev->kobj, gen6_attrs);
> > -     if (ret)
> > -             drm_err(&dev_priv->drm, "RPS sysfs setup failed\n");
> > +     dev_priv->sysfs_gt = i915_setup_gt_sysfs(&kdev->kobj);
> > +     if (!dev_priv->sysfs_gt)
> > +             drm_err(&dev_priv->drm,
> > +                     "failed to register GT sysfs directory\n");
> >   
> >       i915_setup_error_capture(kdev);
> >   
> > @@ -548,14 +261,6 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv)
> >   
> >       i915_teardown_error_capture(kdev);
> >   
> > -     if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> > -             sysfs_remove_files(&kdev->kobj, vlv_attrs);
> > -     else
> > -             sysfs_remove_files(&kdev->kobj, gen6_attrs);
> >       device_remove_bin_file(kdev,  &dpf_attrs_1);
> >       device_remove_bin_file(kdev,  &dpf_attrs);
> > -#ifdef CONFIG_PM
> > -     sysfs_unmerge_group(&kdev->kobj, &rc6_attr_group);
> > -     sysfs_unmerge_group(&kdev->kobj, &rc6p_attr_group);
> > -#endif
> >   }
> > diff --git a/drivers/gpu/drm/i915/i915_sysfs.h b/drivers/gpu/drm/i915/i915_sysfs.h
> > index 41afd4366416..243a17741e3f 100644
> > --- a/drivers/gpu/drm/i915/i915_sysfs.h
> > +++ b/drivers/gpu/drm/i915/i915_sysfs.h
> > @@ -6,8 +6,11 @@
> >   #ifndef __I915_SYSFS_H__
> >   #define __I915_SYSFS_H__
> >   
> > +struct device;
> >   struct drm_i915_private;
> >   
> > +struct drm_i915_private *kdev_minor_to_i915(struct device *kdev);
> > +
> >   void i915_setup_sysfs(struct drm_i915_private *i915);
> >   void i915_teardown_sysfs(struct drm_i915_private *i915);
> >   
> > 
> 
> Regards,
> 
> Tvrtko

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

* Re: [Intel-gfx] [PATCH v3 2/2] drm/i915/gt: make a gt sysfs group and move power management files
@ 2022-01-19  7:19       ` Joonas Lahtinen
  0 siblings, 0 replies; 17+ messages in thread
From: Joonas Lahtinen @ 2022-01-19  7:19 UTC (permalink / raw)
  To: Andi Shyti, DRI Devel, Intel GFX, Tvrtko Ursulin
  Cc: Lucas De Marchi, Matthew Auld

Quoting Tvrtko Ursulin (2022-01-17 18:02:50)
> 
> On 17/01/2022 15:09, Andi Shyti wrote:
> > The GT has its own properties and in sysfs they should be grouped
> > in the 'gt/' directory.
> > 
> > Create a 'gt/' directory in sysfs which will contain gt0...gtN
> > directories related to each tile configured in the GPU. Move the
> > power management files inside those directories.
> > 
> > The previous power management files are kept in their original
> > root directory to avoid breaking the ABI. They point to the tile
> > '0' and a warning message is printed whenever accessed to.

This is wrong. They should act as multiplexers to all the tiles.

Needs to be fixed before merging.

> > The
> > deprecated interface needs for the CONFIG_SYSFS_DEPRECATED_V2
> > flag in order to be generated.
> 
> CONFIG_SYSFS_DEPRECATED_V2 idea was abandoned, no? This patch at least 
> does not appear to contain it so please update the commit message to 
> reflect current state.
> 
> Adding Joonas to help address the question of how strict are userspace 
> requirements for sysfs additions. Personally sysadmin use sounds fine to 
> me, although it needs to be mentioned/documented as Matt requested, but 
> I fear it may not be enough to upstream. Is Level0 at the stage where we 
> can upstream for it I am also not sure.

Sysadmin usage is fine for the simple interfaces that can truly be used
from the command line. This patch seems to just expose the existing
interface in per-tile manner, so should not be a concern.

However, the controls not under gt directories, need to be converted to
apply to all tiles. (I've definitely given that feedback multiple
times). Otherwise it will be very unexpected to the end user when what
previously applied to whole device would only apply to part of it.

Regards, Joonas

> 
> While I am here I also left some nits below (not full review).
> 
> > 
> > The new sysfs structure will have a similar layout for the 4 tile
> > case:
> > 
> > /sys/.../card0
> >           \u251c\u2500\u2500 gt
> >           \u2502   \u251c\u2500\u2500 gt0
> >           \u2502   \u2502   \u251c\u2500\u2500 id
> >           \u2502   \u2502   \u251c\u2500\u2500 rc6_enable
> >           \u2502   \u2502   \u251c\u2500\u2500 rc6_residency_ms
> >           \u2502   \u2502   \u251c\u2500\u2500 rps_act_freq_mhz
> >           \u2502   \u2502   \u251c\u2500\u2500 rps_boost_freq_mhz
> >           \u2502   \u2502   \u251c\u2500\u2500 rps_cur_freq_mhz
> >           \u2502   \u2502   \u251c\u2500\u2500 rps_max_freq_mhz
> >           \u2502   \u2502   \u251c\u2500\u2500 rps_min_freq_mhz
> >           \u2502   \u2502   \u251c\u2500\u2500 rps_RP0_freq_mhz
> >           \u2502   \u2502   \u251c\u2500\u2500 rps_RP1_freq_mhz
> >           \u2502   \u2502   \u2514\u2500\u2500 rps_RPn_freq_mhz
> >        .   .
> >        .   .
> >        .   .
> >           \u2502   \u2514\u2500\u2500 gt3
> >           \u2502       \u251c\u2500\u2500 id
> >           \u2502       \u251c\u2500\u2500 rc6_enable
> >           \u2502       \u251c\u2500\u2500 rc6_residency_ms
> >           \u2502       \u251c\u2500\u2500 rps_act_freq_mhz
> >           \u2502       \u251c\u2500\u2500 rps_boost_freq_mhz
> >           \u2502       \u251c\u2500\u2500 rps_cur_freq_mhz
> >           \u2502       \u251c\u2500\u2500 rps_max_freq_mhz
> >           \u2502       \u251c\u2500\u2500 rps_min_freq_mhz
> >           \u2502       \u251c\u2500\u2500 rps_RP0_freq_mhz
> >           \u2502       \u251c\u2500\u2500 rps_RP1_freq_mhz
> >           \u2502       \u2514\u2500\u2500 rps_RPn_freq_mhz
> >           \u251c\u2500\u2500 gt_act_freq_mhz   -+
> >           \u251c\u2500\u2500 gt_boost_freq_mhz  |
> >           \u251c\u2500\u2500 gt_cur_freq_mhz    |    Original interface
> >           \u251c\u2500\u2500 gt_max_freq_mhz    +\u2500-> kept as existing ABI;
> >           \u251c\u2500\u2500 gt_min_freq_mhz    |    it points to gt0/
> >           \u251c\u2500\u2500 gt_RP0_freq_mhz    |
> >           \u2514\u2500\u2500 gt_RP1_freq_mhz    |
> >           \u2514\u2500\u2500 gt_RPn_freq_mhz   -+
> > 
> > As soon as multitile platforms will start being supported, this
> > interface will allow to control the power (either manually or
> > with tools) on each tile, instead of affecting only tile 0 and
> > getting incomplete results.
> > 
> > Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
> > Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
> > Cc: Matt Roper <matthew.d.roper@intel.com>
> > Cc: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
> > Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> > Reviewed-by: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
> > ---
> >   drivers/gpu/drm/i915/Makefile         |   4 +-
> >   drivers/gpu/drm/i915/gt/intel_gt.c    |   2 +
> >   drivers/gpu/drm/i915/gt/sysfs_gt.c    | 126 +++++++++
> >   drivers/gpu/drm/i915/gt/sysfs_gt.h    |  44 +++
> >   drivers/gpu/drm/i915/gt/sysfs_gt_pm.c | 393 ++++++++++++++++++++++++++
> >   drivers/gpu/drm/i915/gt/sysfs_gt_pm.h |  16 ++
> >   drivers/gpu/drm/i915/i915_drv.h       |   2 +
> >   drivers/gpu/drm/i915/i915_reg.h       |   1 +
> >   drivers/gpu/drm/i915/i915_sysfs.c     | 315 +--------------------
> >   drivers/gpu/drm/i915/i915_sysfs.h     |   3 +
> >   10 files changed, 600 insertions(+), 306 deletions(-)
> >   create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt.c
> >   create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt.h
> >   create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
> >   create mode 100644 drivers/gpu/drm/i915/gt/sysfs_gt_pm.h
> > 
> > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> > index aa86ac33effc..5fd203c626fc 100644
> > --- a/drivers/gpu/drm/i915/Makefile
> > +++ b/drivers/gpu/drm/i915/Makefile
> > @@ -121,7 +121,9 @@ gt-y += \
> >       gt/intel_timeline.o \
> >       gt/intel_workarounds.o \
> >       gt/shmem_utils.o \
> > -     gt/sysfs_engines.o
> > +     gt/sysfs_engines.o \
> > +     gt/sysfs_gt.o \
> > +     gt/sysfs_gt_pm.o
> >   # autogenerated null render state
> >   gt-y += \
> >       gt/gen6_renderstate.o \
> > diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
> > index 17927da9e23e..2584c51c1c14 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_gt.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_gt.c
> > @@ -25,6 +25,7 @@
> >   #include "intel_rps.h"
> >   #include "intel_uncore.h"
> >   #include "shmem_utils.h"
> > +#include "sysfs_gt.h"
> >   #include "pxp/intel_pxp.h"
> >   
> >   static void
> > @@ -453,6 +454,7 @@ void intel_gt_driver_register(struct intel_gt *gt)
> >       intel_rps_driver_register(&gt->rps);
> >   
> >       intel_gt_debugfs_register(gt);
> > +     intel_gt_sysfs_register(gt);
> >   }
> >   
> >   static int intel_gt_init_scratch(struct intel_gt *gt, unsigned int size)
> > diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt.c b/drivers/gpu/drm/i915/gt/sysfs_gt.c
> > new file mode 100644
> > index 000000000000..46cf033a53ec
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/gt/sysfs_gt.c
> > @@ -0,0 +1,126 @@
> > +// SPDX-License-Identifier: MIT
> > +/*
> > + * Copyright © 2020 Intel Corporation
> > + */
> > +
> > +#include <drm/drm_device.h>
> > +#include <linux/device.h>
> > +#include <linux/kobject.h>
> > +#include <linux/printk.h>
> > +#include <linux/sysfs.h>
> > +
> > +#include "i915_drv.h"
> > +#include "i915_sysfs.h"
> > +#include "intel_gt.h"
> > +#include "intel_gt_types.h"
> > +#include "intel_rc6.h"
> > +
> > +#include "sysfs_gt.h"
> > +#include "sysfs_gt_pm.h"
> > +
> > +struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
> > +                                         const char *name)
> > +{
> > +     struct kobject *kobj = &dev->kobj;
> > +
> > +     /*
> > +      * We are interested at knowing from where the interface
> > +      * has been called, whether it's called from gt/ or from
> > +      * the parent directory.
> > +      * From the interface position it depends also the value of
> > +      * the private data.
> > +      * If the interface is called from gt/ then private data is
> > +      * of the "struct intel_gt *" type, otherwise it's * a
> > +      * "struct drm_i915_private *" type.
> > +      */
> > +     if (!is_object_gt(kobj)) {
> > +             struct drm_i915_private *i915 = kdev_minor_to_i915(dev);
> > +
> > +             pr_devel_ratelimited(DEPRECATED
> > +                     "%s (pid %d) is trying to access deprecated %s "
> > +                     "sysfs control, please use gt/gt<n>/%s instead\n",
> 
> Maybe reword "is trying to access" to "is accesing" to remove any doubt 
> whether something is failing or not?
> 
> > +                     current->comm, task_pid_nr(current), name, name);
> > +             return to_gt(i915);
> > +     }
> > +
> > +     return kobj_to_gt(kobj);
> > +}
> > +
> > +static struct kobject *gt_get_parent_obj(struct intel_gt *gt)
> > +{
> > +     return &gt->i915->drm.primary->kdev->kobj;
> > +}
> > +
> > +static ssize_t id_show(struct device *dev,
> > +                    struct device_attribute *attr,
> > +                    char *buf)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +
> > +     return sysfs_emit(buf, "%u\n", gt->info.id);
> > +}
> > +
> > +static DEVICE_ATTR_RO(id);
> > +
> > +static void kobj_gt_release(struct kobject *kobj)
> > +{
> > +     kfree(kobj);
> > +}
> > +
> > +static struct kobj_type kobj_gt_type = {
> > +     .release = kobj_gt_release,
> > +     .sysfs_ops = &kobj_sysfs_ops
> > +};
> > +
> > +struct kobject *
> > +intel_gt_create_kobj(struct intel_gt *gt, struct kobject *dir, const char *name)
> > +{
> > +     struct kobj_gt *kg;
> > +
> > +     kg = kzalloc(sizeof(*kg), GFP_KERNEL);
> > +     if (!kg)
> > +             return NULL;
> > +
> > +     kobject_init(&kg->base, &kobj_gt_type);
> > +     kg->gt = gt;
> > +
> > +     /* xfer ownership to sysfs tree */
> > +     if (kobject_add(&kg->base, dir, "%s", name)) {
> > +             kobject_put(&kg->base);
> > +             return NULL;
> > +     }
> > +
> > +     return &kg->base; /* borrowed ref */
> > +}
> > +
> > +void intel_gt_sysfs_register(struct intel_gt *gt)
> > +{
> > +     struct kobject *dir;
> > +     char name[80];
> > +
> > +     /*
> > +      * We need to make things right with the
> > +      * ABI compatibility. The files were originally
> > +      * generated under the parent directory.
> > +      *
> > +      * We generate the files only for gt 0
> > +      * to avoid duplicates.
> > +      */
> > +     if (!gt->info.id)
> > +             intel_gt_sysfs_pm_init(gt, gt_get_parent_obj(gt));
> > +
> > +     snprintf(name, sizeof(name), "gt%d", gt->info.id);
> > +
> > +     dir = intel_gt_create_kobj(gt, gt->i915->sysfs_gt, name);
> > +     if (!dir) {
> > +             drm_err(&gt->i915->drm,
> > +                     "failed to initialize %s sysfs root\n", name);
> > +             return;
> > +     }
> > +
> > +     if (sysfs_create_file(dir, &dev_attr_id.attr))
> > +             drm_err(&gt->i915->drm,
> > +                     "failed to create sysfs %s info files\n", name);
> 
> These drm_err could maybe be warn or notice, to reflect the fact driver 
> is most likely completely functional? But only maybe since I haven't 
> checked what we do for other sysfs failures. If rest are drm_err then I 
> guess consistency trumps it.
> 
> > +
> > +     intel_gt_sysfs_pm_init(gt, dir);
> > +}
> > diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt.h b/drivers/gpu/drm/i915/gt/sysfs_gt.h
> > new file mode 100644
> > index 000000000000..cd80a14bb14d
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/gt/sysfs_gt.h
> > @@ -0,0 +1,44 @@
> > +/* SPDX-License-Identifier: MIT */
> > +/*
> > + * Copyright © 2020 Intel Corporation
> > + */
> > +
> > +#ifndef __SYSFS_GT_H__
> > +#define __SYSFS_GT_H__
> > +
> > +#include <linux/ctype.h>
> > +#include <linux/kobject.h>
> > +
> > +#include "i915_gem.h" /* GEM_BUG_ON() */
> > +
> > +struct intel_gt;
> > +
> > +struct kobj_gt {
> > +     struct kobject base;
> > +     struct intel_gt *gt;
> > +};
> > +
> > +static inline bool is_object_gt(struct kobject *kobj)
> > +{
> > +     bool b = !strncmp(kobj->name, "gt", 2);
> > +
> > +     GEM_BUG_ON(b && !isdigit(kobj->name[2]));
> 
> 1)
> Not sure what is the point of this GEM_BUG_ON? Checking strncmp works 
> feels like an overkill.
> 
> 2)
> With the recent trend of "static inline considered harmful" perhaps 
> consider moving it out of line.
> 
> > +
> > +     return b;
> > +}
> > +
> > +struct kobject *
> > +intel_gt_create_kobj(struct intel_gt *gt,
> > +                  struct kobject *dir,
> > +                  const char *name);
> > +
> > +static inline struct intel_gt *kobj_to_gt(struct kobject *kobj)
> > +{
> > +     return container_of(kobj, struct kobj_gt, base)->gt;
> > +}
> > +
> > +void intel_gt_sysfs_register(struct intel_gt *gt);
> > +struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
> > +                                         const char *name);
> > +
> > +#endif /* SYSFS_GT_H */
> > diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt_pm.c b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
> > new file mode 100644
> > index 000000000000..6f4424be42d1
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.c
> > @@ -0,0 +1,393 @@
> > +// SPDX-License-Identifier: MIT
> > +/*
> > + * Copyright © 2020 Intel Corporation
> > + */
> > +
> > +#include <drm/drm_device.h>
> > +#include <linux/sysfs.h>
> > +#include <linux/printk.h>
> > +
> > +#include "i915_drv.h"
> > +#include "intel_gt.h"
> > +#include "intel_rc6.h"
> > +#include "intel_rps.h"
> > +#include "sysfs_gt.h"
> > +#include "sysfs_gt_pm.h"
> > +
> > +#ifdef CONFIG_PM
> > +static u32 get_residency(struct intel_gt *gt, i915_reg_t reg)
> > +{
> > +     intel_wakeref_t wakeref;
> > +     u64 res = 0;
> > +
> > +     with_intel_runtime_pm(gt->uncore->rpm, wakeref)
> > +             res = intel_rc6_residency_us(&gt->rc6, reg);
> > +
> > +     return DIV_ROUND_CLOSEST_ULL(res, 1000);
> > +}
> > +
> > +static ssize_t rc6_enable_show(struct device *dev,
> > +                            struct device_attribute *attr,
> > +                            char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     u8 mask = 0;
> > +
> > +     if (HAS_RC6(gt->i915))
> > +             mask |= BIT(0);
> > +     if (HAS_RC6p(gt->i915))
> > +             mask |= BIT(1);
> > +     if (HAS_RC6pp(gt->i915))
> > +             mask |= BIT(2);
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%x\n", mask);
> > +}
> > +
> > +static ssize_t rc6_residency_ms_show(struct device *dev,
> > +                                  struct device_attribute *attr,
> > +                                  char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     u32 rc6_residency = get_residency(gt, GEN6_GT_GFX_RC6);
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%u\n", rc6_residency);
> > +}
> > +
> > +static ssize_t rc6p_residency_ms_show(struct device *dev,
> > +                                   struct device_attribute *attr,
> > +                                   char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     u32 rc6p_residency = get_residency(gt, GEN6_GT_GFX_RC6p);
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%u\n", rc6p_residency);
> > +}
> > +
> > +static ssize_t rc6pp_residency_ms_show(struct device *dev,
> > +                                    struct device_attribute *attr,
> > +                                    char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     u32 rc6pp_residency = get_residency(gt, GEN6_GT_GFX_RC6pp);
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%u\n", rc6pp_residency);
> > +}
> > +
> > +static ssize_t media_rc6_residency_ms_show(struct device *dev,
> > +                                        struct device_attribute *attr,
> > +                                        char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     u32 rc6_residency = get_residency(gt, VLV_GT_MEDIA_RC6);
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%u\n", rc6_residency);
> > +}
> > +
> > +static DEVICE_ATTR_RO(rc6_enable);
> > +static DEVICE_ATTR_RO(rc6_residency_ms);
> > +static DEVICE_ATTR_RO(rc6p_residency_ms);
> > +static DEVICE_ATTR_RO(rc6pp_residency_ms);
> > +static DEVICE_ATTR_RO(media_rc6_residency_ms);
> > +
> > +static struct attribute *rc6_attrs[] = {
> > +     &dev_attr_rc6_enable.attr,
> > +     &dev_attr_rc6_residency_ms.attr,
> > +     NULL
> > +};
> > +
> > +static struct attribute *rc6p_attrs[] = {
> > +     &dev_attr_rc6p_residency_ms.attr,
> > +     &dev_attr_rc6pp_residency_ms.attr,
> > +     NULL
> > +};
> > +
> > +static struct attribute *media_rc6_attrs[] = {
> > +     &dev_attr_media_rc6_residency_ms.attr,
> > +     NULL
> > +};
> > +
> > +static const struct attribute_group rc6_attr_group[] = {
> > +     { .name = power_group_name, .attrs = rc6_attrs },
> > +     { .attrs = rc6_attrs }
> > +};
> > +
> > +static const struct attribute_group rc6p_attr_group[] = {
> > +     { .name = power_group_name, .attrs = rc6p_attrs },
> > +     { .attrs = rc6p_attrs }
> > +};
> > +
> > +static const struct attribute_group media_rc6_attr_group[] = {
> > +     { .name = power_group_name, .attrs = media_rc6_attrs },
> > +     { .attrs = media_rc6_attrs }
> > +};
> > +
> > +static int __intel_gt_sysfs_create_group(struct kobject *kobj,
> > +                                      const struct attribute_group *grp)
> > +{
> > +     int i = is_object_gt(kobj);
> 
> Is_object_gt returns a bool so can I be pedantic? :) Maybe just omit the 
> local and solve it like that.
> 
> > +
> > +     return i ? sysfs_create_group(kobj, &grp[i]) :
> > +                sysfs_merge_group(kobj, &grp[i]);
> > +}
> > +
> > +static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj)
> > +{
> > +     int ret;
> > +
> > +     if (!HAS_RC6(gt->i915))
> > +             return;
> > +
> > +     ret = __intel_gt_sysfs_create_group(kobj, rc6_attr_group);
> > +     if (ret)
> > +             drm_err(&gt->i915->drm,
> > +                     "failed to create gt%u RC6 sysfs files\n", gt->info.id);
> > +
> > +     if (HAS_RC6p(gt->i915)) {
> > +             ret = __intel_gt_sysfs_create_group(kobj, rc6p_attr_group);
> > +             if (ret)
> > +                     drm_err(&gt->i915->drm,
> > +                             "failed to create gt%u RC6p sysfs files\n",
> > +                             gt->info.id);
> > +     }
> > +
> > +     if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915)) {
> > +             ret = __intel_gt_sysfs_create_group(kobj, media_rc6_attr_group);
> > +             if (ret)
> > +                     drm_err(&gt->i915->drm,
> > +                             "failed to create media %u RC6 sysfs files\n",
> > +                             gt->info.id);
> > +     }
> > +}
> > +#else
> > +static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj)
> > +{
> > +}
> > +#endif /* CONFIG_PM */
> > +
> > +static ssize_t act_freq_mhz_show(struct device *dev,
> > +                              struct device_attribute *attr, char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%d\n",
> > +                     intel_rps_read_actual_frequency(&gt->rps));
> > +}
> > +
> > +static ssize_t cur_freq_mhz_show(struct device *dev,
> > +                              struct device_attribute *attr, char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%d\n",
> > +                      intel_rps_get_requested_frequency(rps));
> > +}
> > +
> > +static ssize_t boost_freq_mhz_show(struct device *dev,
> > +                                struct device_attribute *attr,
> > +                                char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%d\n",
> > +                      intel_rps_get_boost_frequency(rps));
> > +}
> > +
> > +static ssize_t boost_freq_mhz_store(struct device *dev,
> > +                                 struct device_attribute *attr,
> > +                                 const char *buff, size_t count)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +     bool boost = false;
> > +     ssize_t ret;
> > +     u32 val;
> > +
> > +     ret = kstrtou32(buff, 0, &val);
> > +     if (ret)
> > +             return ret;
> > +
> > +     /* Validate against (static) hardware limits */
> > +     val = intel_freq_opcode(rps, val);
> > +     if (val < rps->min_freq || val > rps->max_freq)
> > +             return -EINVAL;
> > +
> > +     mutex_lock(&rps->lock);
> > +     if (val != rps->boost_freq) {
> > +             rps->boost_freq = val;
> > +             boost = atomic_read(&rps->num_waiters);
> > +     }
> > +     mutex_unlock(&rps->lock);
> > +     if (boost)
> > +             schedule_work(&rps->work);
> > +
> > +     return count;
> > +}
> > +
> > +static ssize_t vlv_rpe_freq_mhz_show(struct device *dev,
> > +                                  struct device_attribute *attr, char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%d\n",
> > +                     intel_gpu_freq(rps, rps->efficient_freq));
> > +}
> > +
> > +static ssize_t max_freq_mhz_show(struct device *dev,
> > +                              struct device_attribute *attr,
> > +                              char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +
> > +     return sysfs_emit(buff, "%d\n", intel_rps_get_max_frequency(rps));
> > +}
> > +
> > +static ssize_t max_freq_mhz_store(struct device *dev,
> > +                               struct device_attribute *attr,
> > +                               const char *buff, size_t count)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +     ssize_t ret;
> > +     u32 val;
> > +
> > +     ret = kstrtou32(buff, 0, &val);
> > +     if (ret)
> > +             return ret;
> > +
> > +     ret = intel_rps_set_max_frequency(rps, val);
> > +
> > +     return ret ?: count;
> > +}
> > +
> > +static ssize_t min_freq_mhz_show(struct device *dev,
> > +                              struct device_attribute *attr,
> > +                              char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +
> > +     return sysfs_emit(buff, "%d\n", intel_rps_get_min_frequency(rps));
> > +}
> > +
> > +static ssize_t min_freq_mhz_store(struct device *dev,
> > +                               struct device_attribute *attr,
> > +                               const char *buff, size_t count)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +     ssize_t ret;
> > +     u32 val;
> > +
> > +     ret = kstrtou32(buff, 0, &val);
> > +     if (ret)
> > +             return ret;
> > +
> > +     ret = intel_rps_set_min_frequency(rps, val);
> > +
> > +     return ret ?: count;
> > +}
> > +
> > +#define INTEL_GT_RPS_SYSFS_ATTR(_name, _mode, _show, _store) \
> > +     struct device_attribute dev_attr_gt_##_name = __ATTR(gt_##_name, _mode, _show, _store); \
> > +     struct device_attribute dev_attr_rps_##_name = __ATTR(rps_##_name, _mode, _show, _store)
> > +
> > +#define INTEL_GT_RPS_SYSFS_ATTR_RO(_name)                            \
> > +             INTEL_GT_RPS_SYSFS_ATTR(_name, 0444, _name##_show, NULL)
> > +#define INTEL_GT_RPS_SYSFS_ATTR_RW(_name)                            \
> > +             INTEL_GT_RPS_SYSFS_ATTR(_name, 0644, _name##_show, _name##_store)
> > +
> > +static INTEL_GT_RPS_SYSFS_ATTR_RO(act_freq_mhz);
> > +static INTEL_GT_RPS_SYSFS_ATTR_RO(cur_freq_mhz);
> > +static INTEL_GT_RPS_SYSFS_ATTR_RW(boost_freq_mhz);
> > +static INTEL_GT_RPS_SYSFS_ATTR_RW(max_freq_mhz);
> > +static INTEL_GT_RPS_SYSFS_ATTR_RW(min_freq_mhz);
> > +
> > +static DEVICE_ATTR_RO(vlv_rpe_freq_mhz);
> > +
> > +static ssize_t rps_rp_mhz_show(struct device *dev,
> > +                            struct device_attribute *attr,
> > +                            char *buff);
> > +
> > +static INTEL_GT_RPS_SYSFS_ATTR(RP0_freq_mhz, 0444, rps_rp_mhz_show, NULL);
> > +static INTEL_GT_RPS_SYSFS_ATTR(RP1_freq_mhz, 0444, rps_rp_mhz_show, NULL);
> > +static INTEL_GT_RPS_SYSFS_ATTR(RPn_freq_mhz, 0444, rps_rp_mhz_show, NULL);
> > +
> > +#define GEN6_ATTR(s) { \
> > +             &dev_attr_##s##_act_freq_mhz.attr, \
> > +             &dev_attr_##s##_cur_freq_mhz.attr, \
> > +             &dev_attr_##s##_boost_freq_mhz.attr, \
> > +             &dev_attr_##s##_max_freq_mhz.attr, \
> > +             &dev_attr_##s##_min_freq_mhz.attr, \
> > +             &dev_attr_##s##_RP0_freq_mhz.attr, \
> > +             &dev_attr_##s##_RP1_freq_mhz.attr, \
> > +             &dev_attr_##s##_RPn_freq_mhz.attr, \
> > +             NULL, \
> > +     }
> > +
> > +#define GEN6_RPS_ATTR GEN6_ATTR(rps)
> > +#define GEN6_GT_ATTR  GEN6_ATTR(gt)
> > +
> > +/* For now we have a static number of RP states */
> > +static ssize_t rps_rp_mhz_show(struct device *dev,
> > +                            struct device_attribute *attr,
> > +                            char *buff)
> > +{
> > +     struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
> > +     struct intel_rps *rps = &gt->rps;
> > +     u32 val;
> > +
> > +     if (attr == &dev_attr_gt_RP0_freq_mhz ||
> > +         attr == &dev_attr_rps_RP0_freq_mhz) {
> > +             val = intel_rps_get_rp0_frequency(rps);
> > +     } else if (attr == &dev_attr_gt_RP1_freq_mhz ||
> > +                attr == &dev_attr_rps_RP1_freq_mhz) {
> > +                val = intel_rps_get_rp1_frequency(rps);
> > +     } else if (attr == &dev_attr_gt_RPn_freq_mhz ||
> > +                attr == &dev_attr_rps_RPn_freq_mhz) {
> > +                val = intel_rps_get_rpn_frequency(rps);
> > +     } else {
> > +             GEM_WARN_ON(1);
> > +             return -ENODEV;
> > +     }
> > +
> > +     return scnprintf(buff, PAGE_SIZE, "%d\n", val);
> > +}
> > +
> > +static const struct attribute * const gen6_rps_attrs[] = GEN6_RPS_ATTR;
> > +static const struct attribute * const gen6_gt_attrs[]  = GEN6_GT_ATTR;
> > +
> > +static int intel_sysfs_rps_init(struct intel_gt *gt, struct kobject *kobj,
> > +                             const struct attribute * const *attrs)
> > +{
> > +     int ret;
> > +
> > +     if (GRAPHICS_VER(gt->i915) < 6)
> > +             return 0;
> > +
> > +     ret = sysfs_create_files(kobj, attrs);
> > +     if (ret)
> > +             return ret;
> > +
> > +     if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915))
> > +             ret = sysfs_create_file(kobj, &dev_attr_vlv_rpe_freq_mhz.attr);
> > +
> > +     return ret;
> > +}
> > +
> > +void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj)
> > +{
> > +     int ret;
> > +
> > +     intel_sysfs_rc6_init(gt, kobj);
> > +
> > +     ret = is_object_gt(kobj) ?
> > +           intel_sysfs_rps_init(gt, kobj, gen6_rps_attrs) :
> > +           intel_sysfs_rps_init(gt, kobj, gen6_gt_attrs);
> > +     if (ret)
> > +             drm_err(&gt->i915->drm,
> > +                     "failed to create gt%u RPS sysfs files", gt->info.id);
> > +}
> > diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt_pm.h b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.h
> > new file mode 100644
> > index 000000000000..18c60d929e6d
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/gt/sysfs_gt_pm.h
> > @@ -0,0 +1,16 @@
> > +/* SPDX-License-Identifier: MIT */
> > +/*
> > + * Copyright © 2020 Intel Corporation
> > + */
> > +
> > +#ifndef __SYSFS_GT_PM_H__
> > +#define __SYSFS_GT_PM_H__
> > +
> > +#include <linux/kobject.h>
> > +
> > +#include "intel_gt_types.h"
> > +
> > +void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj);
> > +void intel_gt_sysfs_pm_remove(struct intel_gt *gt, struct kobject *kobj);
> > +
> > +#endif /* SYSFS_RC6_H */
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index ec76011366fb..f11acbc0990b 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -989,6 +989,8 @@ struct drm_i915_private {
> >   #define I915_MAX_GT 4
> >       struct intel_gt *gt[I915_MAX_GT];
> >   
> > +     struct kobject *sysfs_gt;
> > +
> >       struct {
> >               struct i915_gem_contexts {
> >                       spinlock_t lock; /* locks list */
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index ef6bc8180073..5153b3ff41e9 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -8480,6 +8480,7 @@ enum {
> >   #define   GEN6_AGGRESSIVE_TURBO                     (0 << 15)
> >   #define   GEN9_SW_REQ_UNSLICE_RATIO_SHIFT   23
> >   #define   GEN9_IGNORE_SLICE_RATIO           (0 << 0)
> > +#define   GEN12_SW_REQ_UNSLICE_RATIO_SHIFT   23
> 
> Stray something?
> 
> >   
> >   #define GEN6_RC_VIDEO_FREQ                  _MMIO(0xA00C)
> >   #define GEN6_RC_CONTROL                             _MMIO(0xA090)
> > diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
> > index fae4d1f4f275..d6687e33f29d 100644
> > --- a/drivers/gpu/drm/i915/i915_sysfs.c
> > +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> > @@ -38,113 +38,12 @@
> >   #include "i915_sysfs.h"
> >   #include "intel_pm.h"
> >   
> > -static inline struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
> > +struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
> >   {
> >       struct drm_minor *minor = dev_get_drvdata(kdev);
> >       return to_i915(minor->dev);
> >   }
> >   
> > -#ifdef CONFIG_PM
> > -static u32 calc_residency(struct drm_i915_private *dev_priv,
> > -                       i915_reg_t reg)
> > -{
> > -     intel_wakeref_t wakeref;
> > -     u64 res = 0;
> > -
> > -     with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref)
> > -             res = intel_rc6_residency_us(&to_gt(dev_priv)->rc6, reg);
> > -
> > -     return DIV_ROUND_CLOSEST_ULL(res, 1000);
> > -}
> > -
> > -static ssize_t rc6_enable_show(struct device *kdev,
> > -                            struct device_attribute *attr, char *buf)
> > -{
> > -     struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> > -     unsigned int mask;
> > -
> > -     mask = 0;
> > -     if (HAS_RC6(dev_priv))
> > -             mask |= BIT(0);
> > -     if (HAS_RC6p(dev_priv))
> > -             mask |= BIT(1);
> > -     if (HAS_RC6pp(dev_priv))
> > -             mask |= BIT(2);
> > -
> > -     return sysfs_emit(buf, "%x\n", mask);
> > -}
> > -
> > -static ssize_t rc6_residency_ms_show(struct device *kdev,
> > -                                  struct device_attribute *attr, char *buf)
> > -{
> > -     struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> > -     u32 rc6_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6);
> > -     return sysfs_emit(buf, "%u\n", rc6_residency);
> > -}
> > -
> > -static ssize_t rc6p_residency_ms_show(struct device *kdev,
> > -                                   struct device_attribute *attr, char *buf)
> > -{
> > -     struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> > -     u32 rc6p_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6p);
> > -     return sysfs_emit(buf, "%u\n", rc6p_residency);
> > -}
> > -
> > -static ssize_t rc6pp_residency_ms_show(struct device *kdev,
> > -                                    struct device_attribute *attr, char *buf)
> > -{
> > -     struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> > -     u32 rc6pp_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6pp);
> > -     return sysfs_emit(buf, "%u\n", rc6pp_residency);
> > -}
> > -
> > -static ssize_t media_rc6_residency_ms_show(struct device *kdev,
> > -                                        struct device_attribute *attr, char *buf)
> > -{
> > -     struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> > -     u32 rc6_residency = calc_residency(dev_priv, VLV_GT_MEDIA_RC6);
> > -     return sysfs_emit(buf, "%u\n", rc6_residency);
> > -}
> > -
> > -static DEVICE_ATTR_RO(rc6_enable);
> > -static DEVICE_ATTR_RO(rc6_residency_ms);
> > -static DEVICE_ATTR_RO(rc6p_residency_ms);
> > -static DEVICE_ATTR_RO(rc6pp_residency_ms);
> > -static DEVICE_ATTR_RO(media_rc6_residency_ms);
> > -
> > -static struct attribute *rc6_attrs[] = {
> > -     &dev_attr_rc6_enable.attr,
> > -     &dev_attr_rc6_residency_ms.attr,
> > -     NULL
> > -};
> > -
> > -static const struct attribute_group rc6_attr_group = {
> > -     .name = power_group_name,
> > -     .attrs =  rc6_attrs
> > -};
> > -
> > -static struct attribute *rc6p_attrs[] = {
> > -     &dev_attr_rc6p_residency_ms.attr,
> > -     &dev_attr_rc6pp_residency_ms.attr,
> > -     NULL
> > -};
> > -
> > -static const struct attribute_group rc6p_attr_group = {
> > -     .name = power_group_name,
> > -     .attrs =  rc6p_attrs
> > -};
> > -
> > -static struct attribute *media_rc6_attrs[] = {
> > -     &dev_attr_media_rc6_residency_ms.attr,
> > -     NULL
> > -};
> > -
> > -static const struct attribute_group media_rc6_attr_group = {
> > -     .name = power_group_name,
> > -     .attrs =  media_rc6_attrs
> > -};
> > -#endif
> > -
> >   static int l3_access_valid(struct drm_i915_private *i915, loff_t offset)
> >   {
> >       if (!HAS_L3_DPF(i915))
> > @@ -256,171 +155,6 @@ static const struct bin_attribute dpf_attrs_1 = {
> >       .private = (void *)1
> >   };
> >   
> > -static ssize_t gt_act_freq_mhz_show(struct device *kdev,
> > -                                 struct device_attribute *attr, char *buf)
> > -{
> > -     struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
> > -     struct intel_rps *rps = &to_gt(i915)->rps;
> > -
> > -     return sysfs_emit(buf, "%d\n", intel_rps_read_actual_frequency(rps));
> > -}
> > -
> > -static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
> > -                                 struct device_attribute *attr, char *buf)
> > -{
> > -     struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
> > -     struct intel_rps *rps = &to_gt(i915)->rps;
> > -
> > -     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)
> > -{
> > -     struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
> > -     struct intel_rps *rps = &to_gt(i915)->rps;
> > -
> > -     return sysfs_emit(buf, "%d\n", intel_rps_get_boost_frequency(rps));
> > -}
> > -
> > -static ssize_t gt_boost_freq_mhz_store(struct device *kdev,
> > -                                    struct device_attribute *attr,
> > -                                    const char *buf, size_t count)
> > -{
> > -     struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> > -     struct intel_rps *rps = &to_gt(dev_priv)->rps;
> > -     ssize_t ret;
> > -     u32 val;
> > -
> > -     ret = kstrtou32(buf, 0, &val);
> > -     if (ret)
> > -             return ret;
> > -
> > -     ret = intel_rps_set_boost_frequency(rps, val);
> > -
> > -     return ret ?: count;
> > -}
> > -
> > -static ssize_t vlv_rpe_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 = &to_gt(dev_priv)->rps;
> > -
> > -     return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->efficient_freq));
> > -}
> > -
> > -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_gt *gt = to_gt(dev_priv);
> > -     struct intel_rps *rps = &gt->rps;
> > -
> > -     return sysfs_emit(buf, "%d\n", intel_rps_get_max_frequency(rps));
> > -}
> > -
> > -static ssize_t gt_max_freq_mhz_store(struct device *kdev,
> > -                                  struct device_attribute *attr,
> > -                                  const char *buf, size_t count)
> > -{
> > -     struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
> > -     struct intel_gt *gt = to_gt(dev_priv);
> > -     struct intel_rps *rps = &gt->rps;
> > -     ssize_t ret;
> > -     u32 val;
> > -
> > -     ret = kstrtou32(buf, 0, &val);
> > -     if (ret)
> > -             return ret;
> > -
> > -     ret = intel_rps_set_max_frequency(rps, val);
> > -
> > -     return ret ?: count;
> > -}
> > -
> > -static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
> > -{
> > -     struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
> > -     struct intel_gt *gt = to_gt(i915);
> > -     struct intel_rps *rps = &gt->rps;
> > -
> > -     return sysfs_emit(buf, "%d\n", intel_rps_get_min_frequency(rps));
> > -}
> > -
> > -static ssize_t gt_min_freq_mhz_store(struct device *kdev,
> > -                                  struct device_attribute *attr,
> > -                                  const char *buf, size_t count)
> > -{
> > -     struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
> > -     struct intel_rps *rps = &to_gt(i915)->rps;
> > -     ssize_t ret;
> > -     u32 val;
> > -
> > -     ret = kstrtou32(buf, 0, &val);
> > -     if (ret)
> > -             return ret;
> > -
> > -     ret = intel_rps_set_min_frequency(rps, val);
> > -
> > -     return ret ?: count;
> > -}
> > -
> > -static DEVICE_ATTR_RO(gt_act_freq_mhz);
> > -static DEVICE_ATTR_RO(gt_cur_freq_mhz);
> > -static DEVICE_ATTR_RW(gt_boost_freq_mhz);
> > -static DEVICE_ATTR_RW(gt_max_freq_mhz);
> > -static DEVICE_ATTR_RW(gt_min_freq_mhz);
> > -
> > -static DEVICE_ATTR_RO(vlv_rpe_freq_mhz);
> > -
> > -static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf);
> > -static DEVICE_ATTR(gt_RP0_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
> > -static DEVICE_ATTR(gt_RP1_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
> > -static DEVICE_ATTR(gt_RPn_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
> > -
> > -/* For now we have a static number of RP states */
> > -static ssize_t gt_rp_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 = &to_gt(dev_priv)->rps;
> > -     u32 val;
> > -
> > -     if (attr == &dev_attr_gt_RP0_freq_mhz)
> > -             val = intel_rps_get_rp0_frequency(rps);
> > -     else if (attr == &dev_attr_gt_RP1_freq_mhz)
> > -             val = intel_rps_get_rp1_frequency(rps);
> > -     else if (attr == &dev_attr_gt_RPn_freq_mhz)
> > -             val = intel_rps_get_rpn_frequency(rps);
> > -     else
> > -             BUG();
> > -
> > -     return sysfs_emit(buf, "%d\n", val);
> > -}
> > -
> > -static const struct attribute * const gen6_attrs[] = {
> > -     &dev_attr_gt_act_freq_mhz.attr,
> > -     &dev_attr_gt_cur_freq_mhz.attr,
> > -     &dev_attr_gt_boost_freq_mhz.attr,
> > -     &dev_attr_gt_max_freq_mhz.attr,
> > -     &dev_attr_gt_min_freq_mhz.attr,
> > -     &dev_attr_gt_RP0_freq_mhz.attr,
> > -     &dev_attr_gt_RP1_freq_mhz.attr,
> > -     &dev_attr_gt_RPn_freq_mhz.attr,
> > -     NULL,
> > -};
> > -
> > -static const struct attribute * const vlv_attrs[] = {
> > -     &dev_attr_gt_act_freq_mhz.attr,
> > -     &dev_attr_gt_cur_freq_mhz.attr,
> > -     &dev_attr_gt_boost_freq_mhz.attr,
> > -     &dev_attr_gt_max_freq_mhz.attr,
> > -     &dev_attr_gt_min_freq_mhz.attr,
> > -     &dev_attr_gt_RP0_freq_mhz.attr,
> > -     &dev_attr_gt_RP1_freq_mhz.attr,
> > -     &dev_attr_gt_RPn_freq_mhz.attr,
> > -     &dev_attr_vlv_rpe_freq_mhz.attr,
> > -     NULL,
> > -};
> > -
> >   #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
> >   
> >   static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
> > @@ -486,34 +220,16 @@ static void i915_setup_error_capture(struct device *kdev) {}
> >   static void i915_teardown_error_capture(struct device *kdev) {}
> >   #endif
> >   
> > +static struct kobject *i915_setup_gt_sysfs(struct kobject *parent)
> > +{
> > +     return kobject_create_and_add("gt", parent);
> > +}
> > +
> >   void i915_setup_sysfs(struct drm_i915_private *dev_priv)
> >   {
> >       struct device *kdev = dev_priv->drm.primary->kdev;
> >       int ret;
> >   
> > -#ifdef CONFIG_PM
> > -     if (HAS_RC6(dev_priv)) {
> > -             ret = sysfs_merge_group(&kdev->kobj,
> > -                                     &rc6_attr_group);
> > -             if (ret)
> > -                     drm_err(&dev_priv->drm,
> > -                             "RC6 residency sysfs setup failed\n");
> > -     }
> > -     if (HAS_RC6p(dev_priv)) {
> > -             ret = sysfs_merge_group(&kdev->kobj,
> > -                                     &rc6p_attr_group);
> > -             if (ret)
> > -                     drm_err(&dev_priv->drm,
> > -                             "RC6p residency sysfs setup failed\n");
> > -     }
> > -     if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> > -             ret = sysfs_merge_group(&kdev->kobj,
> > -                                     &media_rc6_attr_group);
> > -             if (ret)
> > -                     drm_err(&dev_priv->drm,
> > -                             "Media RC6 residency sysfs setup failed\n");
> > -     }
> > -#endif
> >       if (HAS_L3_DPF(dev_priv)) {
> >               ret = device_create_bin_file(kdev, &dpf_attrs);
> >               if (ret)
> > @@ -529,13 +245,10 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv)
> >               }
> >       }
> >   
> > -     ret = 0;
> > -     if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> > -             ret = sysfs_create_files(&kdev->kobj, vlv_attrs);
> > -     else if (GRAPHICS_VER(dev_priv) >= 6)
> > -             ret = sysfs_create_files(&kdev->kobj, gen6_attrs);
> > -     if (ret)
> > -             drm_err(&dev_priv->drm, "RPS sysfs setup failed\n");
> > +     dev_priv->sysfs_gt = i915_setup_gt_sysfs(&kdev->kobj);
> > +     if (!dev_priv->sysfs_gt)
> > +             drm_err(&dev_priv->drm,
> > +                     "failed to register GT sysfs directory\n");
> >   
> >       i915_setup_error_capture(kdev);
> >   
> > @@ -548,14 +261,6 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv)
> >   
> >       i915_teardown_error_capture(kdev);
> >   
> > -     if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> > -             sysfs_remove_files(&kdev->kobj, vlv_attrs);
> > -     else
> > -             sysfs_remove_files(&kdev->kobj, gen6_attrs);
> >       device_remove_bin_file(kdev,  &dpf_attrs_1);
> >       device_remove_bin_file(kdev,  &dpf_attrs);
> > -#ifdef CONFIG_PM
> > -     sysfs_unmerge_group(&kdev->kobj, &rc6_attr_group);
> > -     sysfs_unmerge_group(&kdev->kobj, &rc6p_attr_group);
> > -#endif
> >   }
> > diff --git a/drivers/gpu/drm/i915/i915_sysfs.h b/drivers/gpu/drm/i915/i915_sysfs.h
> > index 41afd4366416..243a17741e3f 100644
> > --- a/drivers/gpu/drm/i915/i915_sysfs.h
> > +++ b/drivers/gpu/drm/i915/i915_sysfs.h
> > @@ -6,8 +6,11 @@
> >   #ifndef __I915_SYSFS_H__
> >   #define __I915_SYSFS_H__
> >   
> > +struct device;
> >   struct drm_i915_private;
> >   
> > +struct drm_i915_private *kdev_minor_to_i915(struct device *kdev);
> > +
> >   void i915_setup_sysfs(struct drm_i915_private *i915);
> >   void i915_teardown_sysfs(struct drm_i915_private *i915);
> >   
> > 
> 
> Regards,
> 
> Tvrtko

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

* Re: [Intel-gfx] [PATCH v3 2/2] drm/i915/gt: make a gt sysfs group and move power management files
  2022-01-19  7:19       ` Joonas Lahtinen
@ 2022-01-19  9:00         ` Andi Shyti
  -1 siblings, 0 replies; 17+ messages in thread
From: Andi Shyti @ 2022-01-19  9:00 UTC (permalink / raw)
  To: Joonas Lahtinen
  Cc: Tvrtko Ursulin, Abdiel Janulgue, Intel GFX, Lucas De Marchi,
	DRI Devel, Matthew Auld, Andi Shyti

Hi Joonas,

> > > The GT has its own properties and in sysfs they should be grouped
> > > in the 'gt/' directory.
> > > 
> > > Create a 'gt/' directory in sysfs which will contain gt0...gtN
> > > directories related to each tile configured in the GPU. Move the
> > > power management files inside those directories.
> > > 
> > > The previous power management files are kept in their original
> > > root directory to avoid breaking the ABI. They point to the tile
> > > '0' and a warning message is printed whenever accessed to.
> 
> This is wrong. They should act as multiplexers to all the tiles.
> 
> Needs to be fixed before merging.

I have a patch for this and I planned to send it later. I have
even been asked to split this one in more chunks as the review is
a bit difficult.

> > > The
> > > deprecated interface needs for the CONFIG_SYSFS_DEPRECATED_V2
> > > flag in order to be generated.
> > 
> > CONFIG_SYSFS_DEPRECATED_V2 idea was abandoned, no? This patch at least 
> > does not appear to contain it so please update the commit message to 
> > reflect current state.
> > 
> > Adding Joonas to help address the question of how strict are userspace 
> > requirements for sysfs additions. Personally sysadmin use sounds fine to 
> > me, although it needs to be mentioned/documented as Matt requested, but 
> > I fear it may not be enough to upstream. Is Level0 at the stage where we 
> > can upstream for it I am also not sure.
> 
> Sysadmin usage is fine for the simple interfaces that can truly be used
> from the command line. This patch seems to just expose the existing
> interface in per-tile manner, so should not be a concern.

This will definitely help this patch (series) to get in, but I
my understanding is that Level0 is a bit behind for upstreaming.

> However, the controls not under gt directories, need to be converted to
> apply to all tiles. (I've definitely given that feedback multiple
> times). Otherwise it will be very unexpected to the end user when what
> previously applied to whole device would only apply to part of it.

It's not forgotten :)

> Regards, Joonas

Thank you,
Andi

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

* Re: [Intel-gfx] [PATCH v3 2/2] drm/i915/gt: make a gt sysfs group and move power management files
@ 2022-01-19  9:00         ` Andi Shyti
  0 siblings, 0 replies; 17+ messages in thread
From: Andi Shyti @ 2022-01-19  9:00 UTC (permalink / raw)
  To: Joonas Lahtinen; +Cc: Intel GFX, Lucas De Marchi, DRI Devel, Matthew Auld

Hi Joonas,

> > > The GT has its own properties and in sysfs they should be grouped
> > > in the 'gt/' directory.
> > > 
> > > Create a 'gt/' directory in sysfs which will contain gt0...gtN
> > > directories related to each tile configured in the GPU. Move the
> > > power management files inside those directories.
> > > 
> > > The previous power management files are kept in their original
> > > root directory to avoid breaking the ABI. They point to the tile
> > > '0' and a warning message is printed whenever accessed to.
> 
> This is wrong. They should act as multiplexers to all the tiles.
> 
> Needs to be fixed before merging.

I have a patch for this and I planned to send it later. I have
even been asked to split this one in more chunks as the review is
a bit difficult.

> > > The
> > > deprecated interface needs for the CONFIG_SYSFS_DEPRECATED_V2
> > > flag in order to be generated.
> > 
> > CONFIG_SYSFS_DEPRECATED_V2 idea was abandoned, no? This patch at least 
> > does not appear to contain it so please update the commit message to 
> > reflect current state.
> > 
> > Adding Joonas to help address the question of how strict are userspace 
> > requirements for sysfs additions. Personally sysadmin use sounds fine to 
> > me, although it needs to be mentioned/documented as Matt requested, but 
> > I fear it may not be enough to upstream. Is Level0 at the stage where we 
> > can upstream for it I am also not sure.
> 
> Sysadmin usage is fine for the simple interfaces that can truly be used
> from the command line. This patch seems to just expose the existing
> interface in per-tile manner, so should not be a concern.

This will definitely help this patch (series) to get in, but I
my understanding is that Level0 is a bit behind for upstreaming.

> However, the controls not under gt directories, need to be converted to
> apply to all tiles. (I've definitely given that feedback multiple
> times). Otherwise it will be very unexpected to the end user when what
> previously applied to whole device would only apply to part of it.

It's not forgotten :)

> Regards, Joonas

Thank you,
Andi

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

end of thread, other threads:[~2022-01-19  9:00 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-17 15:09 [PATCH v3 0/2] Introduce multitile support Andi Shyti
2022-01-17 15:09 ` [Intel-gfx] " Andi Shyti
2022-01-17 15:09 ` [PATCH v3 1/2] drm/i915: Prepare for multiple GTs Andi Shyti
2022-01-17 15:09   ` [Intel-gfx] " Andi Shyti
2022-01-17 15:09 ` [PATCH v3 2/2] drm/i915/gt: make a gt sysfs group and move power management files Andi Shyti
2022-01-17 15:09   ` [Intel-gfx] " Andi Shyti
2022-01-17 16:02   ` Tvrtko Ursulin
2022-01-17 17:16     ` Andi Shyti
2022-01-17 17:16       ` Andi Shyti
2022-01-19  7:19     ` Joonas Lahtinen
2022-01-19  7:19       ` Joonas Lahtinen
2022-01-19  9:00       ` Andi Shyti
2022-01-19  9:00         ` Andi Shyti
2022-01-17 15:38 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for Introduce multitile support Patchwork
2022-01-17 15:39 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2022-01-17 16:09 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork
2022-01-17 17:57 ` [Intel-gfx] ✗ Fi.CI.IGT: " Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.