[Intel-gfx] [PATCH v4 10/26] drm/i915/slpc: Allocate/Release/Initialize SLPC shared data

Chris Wilson chris at chris-wilson.co.uk
Fri Sep 9 17:08:46 UTC 2016


On Fri, Sep 09, 2016 at 06:21:29PM +0530, Sagar Arun Kamble wrote:
> 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).
> 
> Reviewed-by: David Weinehall <david.weinehall at linux.intel.com>
> 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_drv.h  |  7 ++-
>  drivers/gpu/drm/i915/intel_guc.h  |  2 +
>  drivers/gpu/drm/i915/intel_pm.c   |  6 ++-
>  drivers/gpu/drm/i915/intel_slpc.c | 88 ++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_slpc.h | 99 +++++++++++++++++++++++++++++++++++++++
>  5 files changed, 199 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index cf9aa24..796c52f 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1707,7 +1707,12 @@ bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
>  

I am going to need an idiot's guide here as to the difference between
enabled() and active().

>  static inline int intel_slpc_active(struct drm_i915_private *dev_priv)

bool.

>  {
> -	return 0;
> +	int ret = 0;
> +
> +	if (dev_priv->guc.slpc.vma && dev_priv->guc.slpc.enabled)
> +		ret = 1;
> +
> +	return ret;
>  }
>  
>  /* intel_pm.c */
> diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
> index 83dec66..6e24e60 100644
> --- a/drivers/gpu/drm/i915/intel_guc.h
> +++ b/drivers/gpu/drm/i915/intel_guc.h
> @@ -145,6 +145,8 @@ struct intel_guc {
>  
>  	uint64_t submissions[I915_NUM_ENGINES];
>  	uint32_t last_seqno[I915_NUM_ENGINES];
> +
> +	struct intel_slpc slpc;
>  };
>  
>  static inline int intel_slpc_enabled(void)
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index d187066..2211f7b 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -6656,7 +6656,8 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv)
>  
>  void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv)
>  {
> -	if (intel_slpc_enabled())
> +	if (intel_slpc_enabled() &&
> +	    dev_priv->guc.slpc.vma)
>  		intel_slpc_cleanup(dev_priv);
>  	else if (IS_VALLEYVIEW(dev_priv))
>  		valleyview_cleanup_gt_powersave(dev_priv);
> @@ -6746,7 +6747,8 @@ void intel_enable_gt_powersave(struct drm_i915_private *dev_priv)
>  
>  	mutex_lock(&dev_priv->rps.hw_lock);
>  
> -	if (intel_slpc_enabled()) {
> +	if (intel_slpc_enabled() &&
> +	    dev_priv->guc.slpc.vma) {
>  		gen9_enable_rc6(dev_priv);
>  		intel_slpc_enable(dev_priv);
>  		if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
> diff --git a/drivers/gpu/drm/i915/intel_slpc.c b/drivers/gpu/drm/i915/intel_slpc.c
> index be9e84c..972db18 100644
> --- a/drivers/gpu/drm/i915/intel_slpc.c
> +++ b/drivers/gpu/drm/i915/intel_slpc.c
> @@ -22,15 +22,103 @@
>   *
>   */
>  #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 drm_i915_gem_object *obj;
> +	struct page *page;
> +	struct slpc_shared_data *data;
> +	u64 msr_value;
> +
> +	if (!dev_priv->guc.slpc.vma)
> +		return;
> +
> +	obj = dev_priv->guc.slpc.vma->obj;
> +
> +	page = i915_gem_object_get_page(obj, 0);

page = i915_vma_first_pgae(dev_priv->guc.slpc.vma);

and cannot be NULL (by construction in guc_allocate_vma).

> +	if (page) {
> +		data = kmap_atomic(page);
> +		memset(data, 0, sizeof(struct slpc_shared_data));
> +
> +		data->shared_data_size = sizeof(struct slpc_shared_data);
> +		data->global_state = (u32)SLPC_GLOBAL_STATE_NOT_RUNNING;
> +		data->platform_info.platform_sku =
> +					(u8)slpc_get_platform_sku(dev_priv);
> +		data->platform_info.slice_count =
> +					(u8)slpc_get_slice_count(dev_priv);
> +		data->platform_info.power_plan_source =
> +			(u8)SLPC_POWER_PLAN_SOURCE(SLPC_POWER_PLAN_BALANCED,
> +						    SLPC_POWER_SOURCE_AC);
> +		rdmsrl(MSR_TURBO_RATIO_LIMIT, msr_value);
> +		data->platform_info.P0_freq = (u8)msr_value;
> +		rdmsrl(MSR_PLATFORM_INFO, msr_value);
> +		data->platform_info.P1_freq = (u8)(msr_value >> 8);
> +		data->platform_info.Pe_freq = (u8)(msr_value >> 40);
> +		data->platform_info.Pn_freq = (u8)(msr_value >> 48);

The u8 et al are implied anyway, are they not?

> +
> +		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) {

There's always something fishy about init routines called multiple
times.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre


More information about the Intel-gfx mailing list