[PATCH v5 09/23] drm/i915/slpc: Allocate/Release/Initialize SLPC shared data

Sagar Arun Kamble sagar.a.kamble at intel.com
Sat Oct 22 08:17:06 UTC 2016


From: Tom O'Rourke <Tom.O'Rourke at intel.com>

SLPC shared data is used to pass information
to/from SLPC in GuC firmware.

For Skylake, platform sku type and slice count
are identified from device id and fuse values.

Support for other platforms needs to be added.

v1: Update for SLPC interface version 2015.2.4
    intel_slpc_active() returns 1 if slpc initialized (Paulo)
    change default host_os to "Windows"
    Spelling fixes (Sagar Kamble and Nick Hoath)
    Added WARN for checking if upper 32bits of GTT offset
    of shared object are zero. (ChrisW)
    Changed function call from gem_allocate/release_guc_obj to
    i915_guc_allocate/release_gem_obj. (Sagar)
    Updated commit message and moved POWER_PLAN and POWER_SOURCE
    definition from later patch. (Akash)
    Add struct_mutex locking while allocating/releasing slpc shared
    object. This was caught by CI BAT. Adding SLPC state variable
    to determine if it is active as it not just dependent on shared
    data setup.
    Rebase with guc_allocate_vma related changes.

v2: WARN_ON for platform_sku validity and space changes. (David)
    Checkpatch update.

v3: Fixing WARNING in igt at drv_module_reload_basic found in trybot BAT
    with SLPC Enabled.

v4: Updated support for GuC v9. s/slice_total/hweight8(slice_mask)/ (Dave).

v5: SLPC vma mapping changes and removing explicit type conversions. (Chris).

Signed-off-by: Tom O'Rourke <Tom.O'Rourke at intel.com>
Signed-off-by: Sagar Arun Kamble <sagar.a.kamble at intel.com>
---
 drivers/gpu/drm/i915/intel_slpc.c | 81 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_slpc.h | 95 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 176 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_slpc.c b/drivers/gpu/drm/i915/intel_slpc.c
index b67f1bc..9294f8c 100644
--- a/drivers/gpu/drm/i915/intel_slpc.c
+++ b/drivers/gpu/drm/i915/intel_slpc.c
@@ -22,15 +22,96 @@
  *
  */
 #include <linux/firmware.h>
+#include <asm/msr-index.h>
 #include "i915_drv.h"
 #include "intel_guc.h"
 
+static unsigned int slpc_get_platform_sku(struct drm_i915_private *dev_priv)
+{
+	enum slpc_platform_sku platform_sku;
+
+	if (IS_SKL_ULX(dev_priv))
+		platform_sku = SLPC_PLATFORM_SKU_ULX;
+	else if (IS_SKL_ULT(dev_priv))
+		platform_sku = SLPC_PLATFORM_SKU_ULT;
+	else
+		platform_sku = SLPC_PLATFORM_SKU_DT;
+
+	WARN_ON(platform_sku > 0xFF);
+
+	return platform_sku;
+}
+
+static unsigned int slpc_get_slice_count(struct drm_i915_private *dev_priv)
+{
+	unsigned int slice_count = 1;
+
+	if (IS_SKYLAKE(dev_priv))
+		slice_count = hweight8(INTEL_INFO(dev_priv)->sseu.slice_mask);
+
+	return slice_count;
+}
+
+static void slpc_shared_data_init(struct drm_i915_private *dev_priv)
+{
+	struct page *page;
+	struct slpc_shared_data *data;
+	u64 msr_value;
+
+	page = i915_vma_first_page(dev_priv->guc.slpc.vma);
+	data = kmap_atomic(page);
+
+	memset(data, 0, sizeof(struct slpc_shared_data));
+
+	data->shared_data_size = sizeof(struct slpc_shared_data);
+	data->global_state = SLPC_GLOBAL_STATE_NOT_RUNNING;
+	data->platform_info.platform_sku =
+				slpc_get_platform_sku(dev_priv);
+	data->platform_info.slice_count =
+				slpc_get_slice_count(dev_priv);
+	data->platform_info.power_plan_source =
+		SLPC_POWER_PLAN_SOURCE(SLPC_POWER_PLAN_BALANCED,
+					    SLPC_POWER_SOURCE_AC);
+	rdmsrl(MSR_TURBO_RATIO_LIMIT, msr_value);
+	data->platform_info.P0_freq = msr_value;
+	rdmsrl(MSR_PLATFORM_INFO, msr_value);
+	data->platform_info.P1_freq = msr_value >> 8;
+	data->platform_info.Pe_freq = msr_value >> 40;
+	data->platform_info.Pn_freq = msr_value >> 48;
+
+	kunmap_atomic(data);
+}
+
 void intel_slpc_init(struct drm_i915_private *dev_priv)
 {
+	struct intel_guc *guc = &dev_priv->guc;
+	struct i915_vma *vma;
+
+	/* Allocate shared data structure */
+	vma = dev_priv->guc.slpc.vma;
+	if (!vma) {
+		vma = guc_allocate_vma(guc,
+			       PAGE_ALIGN(sizeof(struct slpc_shared_data)));
+		if (IS_ERR(vma)) {
+			DRM_ERROR("slpc_shared_data allocation failed\n");
+			i915.enable_slpc = 0;
+			return;
+		}
+
+		dev_priv->guc.slpc.vma = vma;
+	}
+
+	slpc_shared_data_init(dev_priv);
 }
 
 void intel_slpc_cleanup(struct drm_i915_private *dev_priv)
 {
+	struct intel_guc *guc = &dev_priv->guc;
+
+	/* Release shared data structure */
+	mutex_lock(&dev_priv->drm.struct_mutex);
+	i915_vma_unpin_and_release(&guc->slpc.vma);
+	mutex_unlock(&dev_priv->drm.struct_mutex);
 }
 
 void intel_slpc_suspend(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/intel_slpc.h b/drivers/gpu/drm/i915/intel_slpc.h
index e5acfc8..eb9033f 100644
--- a/drivers/gpu/drm/i915/intel_slpc.h
+++ b/drivers/gpu/drm/i915/intel_slpc.h
@@ -24,8 +24,103 @@
 #ifndef _INTEL_SLPC_H_
 #define _INTEL_SLPC_H_
 
+enum slpc_global_state {
+	SLPC_GLOBAL_STATE_NOT_RUNNING = 0,
+	SLPC_GLOBAL_STATE_INITIALIZING = 1,
+	SLPC_GLOBAL_STATE_RESETTING = 2,
+	SLPC_GLOBAL_STATE_RUNNING = 3,
+	SLPC_GLOBAL_STATE_SHUTTING_DOWN = 4,
+	SLPC_GLOBAL_STATE_ERROR = 5
+};
+
+enum slpc_platform_sku {
+	SLPC_PLATFORM_SKU_UNDEFINED = 0,
+	SLPC_PLATFORM_SKU_ULX = 1,
+	SLPC_PLATFORM_SKU_ULT = 2,
+	SLPC_PLATFORM_SKU_T = 3,
+	SLPC_PLATFORM_SKU_MOBL = 4,
+	SLPC_PLATFORM_SKU_DT = 5,
+	SLPC_PLATFORM_SKU_UNKNOWN = 6,
+};
+
+enum slpc_power_plan {
+	SLPC_POWER_PLAN_UNDEFINED = 0,
+	SLPC_POWER_PLAN_BATTERY_SAVER = 1,
+	SLPC_POWER_PLAN_BALANCED = 2,
+	SLPC_POWER_PLAN_PERFORMANCE = 3,
+	SLPC_POWER_PLAN_UNKNOWN = 4,
+};
+
+enum slpc_power_source {
+	SLPC_POWER_SOURCE_UNDEFINED = 0,
+	SLPC_POWER_SOURCE_AC = 1,
+	SLPC_POWER_SOURCE_DC = 2,
+	SLPC_POWER_SOURCE_UNKNOWN = 3,
+};
+
+#define SLPC_POWER_PLAN_SOURCE(plan, source) ((plan) | ((source) << 6))
+#define SLPC_POWER_PLAN(plan_source) ((plan_source) & 0x3F)
+#define SLPC_POWER_SOURCE(plan_source) ((plan_source) >> 6)
+
+struct slpc_platform_info {
+	u8 platform_sku;
+	u8 slice_count;
+	u8 reserved;
+	u8 power_plan_source;
+	u8 P0_freq;
+	u8 P1_freq;
+	u8 Pe_freq;
+	u8 Pn_freq;
+	u32 reserved1;
+	u32 reserved2;
+} __packed;
+
+struct slpc_task_state_data {
+	union {
+		u32 bitfield1;
+		struct {
+			u32 gtperf_task_active:1;
+			u32 gtperf_stall_possible:1;
+			u32 gtperf_gaming_mode:1;
+			u32 gtperf_target_fps:8;
+			u32 dcc_task_active:1;
+			u32 in_dcc:1;
+			u32 in_dct:1;
+			u32 freq_switch_active:1;
+			u32 ibc_enabled:1;
+			u32 ibc_active:1;
+			u32 pg1_enabled:1;
+			u32 pg1_active:1;
+			u32 reserved:13;
+		};
+	};
+	union {
+		u32 bitfield2;
+		struct {
+			u32 freq_unslice_max:8;
+			u32 freq_unslice_min:8;
+			u32 freq_slice_max:8;
+			u32 freq_slice_min:8;
+		};
+	};
+};
+
+#define SLPC_MAX_OVERRIDE_PARAMETERS 192
+#define SLPC_OVERRIDE_BITFIELD_SIZE ((SLPC_MAX_OVERRIDE_PARAMETERS + 31) / 32)
+
+struct slpc_shared_data {
+	u32 reserved;
+	u32 shared_data_size;
+	u32 global_state;
+	struct slpc_platform_info platform_info;
+	struct slpc_task_state_data task_state_data;
+	u32 override_parameters_set_bits[SLPC_OVERRIDE_BITFIELD_SIZE];
+	u32 override_parameters_values[SLPC_MAX_OVERRIDE_PARAMETERS];
+} __packed;
+
 struct intel_slpc {
 	bool active;
+	struct i915_vma *vma;
 };
 
 /* intel_slpc.c */
-- 
1.9.1



More information about the Intel-gfx-trybot mailing list