[Intel-gfx] [PATCH 20/31] drm/i915/slpc: Add parameter set/unset/get, task control/status functions
Sagar Arun Kamble
sagar.a.kamble at intel.com
Thu Sep 28 09:55:33 UTC 2017
On 9/21/2017 7:17 PM, Michal Wajdeczko wrote:
> On Tue, 19 Sep 2017 19:41:56 +0200, Sagar Arun Kamble
> <sagar.a.kamble at intel.com> wrote:
>
>> SLPC behavior can be changed through set of parameters.
>> These parameters can be updated and queried from i915 though
>> Host to GuC SLPC events. This patch adds parameter update
>> events for setting/unsetting/getting parameters. SLPC has
>> various tasks for controlling different controls. This patch
>> adds functions to control and query the task status.
>>
>> v1: Use host2guc_slpc
>> update slcp_param_id enum values for SLPC 2015.2.4
>> return void instead of ignored error code (Paulo)
>>
>> v2: Checkpatch update.
>>
>> v3: Rebase.
>>
>> v4: Updated with GuC firmware v9.
>>
>> v5: Updated input structure to host2guc_slpc. Added functions
>> to update only parameters in the SLPC shared memory. This
>> will allow to setup shared data with all parameters and send
>> single event to SLPC take them into effect. Commit message
>> update. (Sagar)
>>
>> v6: Rearranged helpers to use them in slpc_shared_data_init.
>> Added definition of SLPC_KMD_MAX_PARAM.
>>
>> v7: Added definition of host2guc_slpc with rearrangement of patches.
>> Added task control/status functions.
>>
>> v8: Rebase w.r.t s/intel_guc_send/intel_guc_send_mmio.
>>
>> Cc: Michal Wajdeczko <michal.wajdeczko at 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_guc.c | 21 ++++-
>> drivers/gpu/drm/i915/intel_guc.h | 2 +
>> drivers/gpu/drm/i915/intel_slpc.c | 185
>> ++++++++++++++++++++++++++++++++++++++
>> drivers/gpu/drm/i915/intel_slpc.h | 8 ++
>> 4 files changed, 215 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_guc.c
>> b/drivers/gpu/drm/i915/intel_guc.c
>> index a92c7e8..656bae9 100644
>> --- a/drivers/gpu/drm/i915/intel_guc.c
>> +++ b/drivers/gpu/drm/i915/intel_guc.c
>> @@ -67,9 +67,11 @@ void intel_guc_init_send_regs(struct intel_guc *guc)
>> /*
>> * This function implements the MMIO based host to GuC interface.
>> */
>> -int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action,
>> u32 len)
>> +int __intel_guc_send_mmio(struct intel_guc *guc, const u32 *action,
>> u32 len,
>> + u32 *output)
>> {
>> struct drm_i915_private *dev_priv = guc_to_i915(guc);
>> + union slpc_event_output_header header;
>
> Don't pollute generic send function with slpc specific code.
Ok. Will prepare new SLPC specific send function built on top of GUC CT
based send.
>
>
>> u32 status;
>> int i;
>> int ret;
>> @@ -115,12 +117,29 @@ int intel_guc_send_mmio(struct intel_guc *guc,
>> const u32 *action, u32 len)
>> action[0], ret, status, I915_READ(SOFT_SCRATCH(15)));
>> }
>> + /*
>> + * Output data from Host to GuC SLPC actions is populated in
>> scratch
>> + * registers SOFT_SCRATCH(1) to SOFT_SCRATCH(14) based on event.
>
> Note that receiving more data over MMIO will be handled by these
> pending patches
> https://patchwork.freedesktop.org/patch/170667/
> https://patchwork.freedesktop.org/patch/170669/
>
> The same series will also add support for responses over CT so stay
> tuned!
Yes. Will base SLPC changes on top of these.
>
>> + * Currently only SLPC action status in GuC is meaningful as Host
>> + * can query only overridden parameters and that are fetched from
>> + * Host-GuC SLPC shared data.
>> + */
>> + if (output && !ret) {
>> + output[0] = header.value = I915_READ(SOFT_SCRATCH(1));
>> + ret = header.status;
>> + }
>> +
>> intel_uncore_forcewake_put(dev_priv, guc->send_regs.fw_domains);
>> mutex_unlock(&guc->send_mutex);
>> return ret;
>> }
>> +int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action,
>> u32 len)
>> +{
>> + return __intel_guc_send_mmio(guc, action, len, NULL);
>> +}
>> +
>> int intel_guc_sample_forcewake(struct intel_guc *guc)
>> {
>> struct drm_i915_private *dev_priv = guc_to_i915(guc);
>> diff --git a/drivers/gpu/drm/i915/intel_guc.h
>> b/drivers/gpu/drm/i915/intel_guc.h
>> index b835d30..c27d2dd 100644
>> --- a/drivers/gpu/drm/i915/intel_guc.h
>> +++ b/drivers/gpu/drm/i915/intel_guc.h
>> @@ -132,6 +132,8 @@ struct intel_guc {
>> int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32
>> len);
>> void gen8_guc_raise_irq(struct intel_guc *guc);
>> void intel_guc_init_send_regs(struct intel_guc *guc);
>> +int __intel_guc_send_mmio(struct intel_guc *guc, const u32 *action,
>> u32 len,
>> + u32 *output);
>> int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action,
>> u32 len);
>> int intel_guc_sample_forcewake(struct intel_guc *guc);
>> int intel_guc_runtime_suspend(struct intel_guc *guc);
>> diff --git a/drivers/gpu/drm/i915/intel_slpc.c
>> b/drivers/gpu/drm/i915/intel_slpc.c
>> index 73e7bf5..f47d81e 100644
>> --- a/drivers/gpu/drm/i915/intel_slpc.c
>> +++ b/drivers/gpu/drm/i915/intel_slpc.c
>> @@ -132,6 +132,191 @@ int slpc_mem_task_control(struct
>> slpc_shared_data *data, u64 val,
>> return ret;
>> }
>> +static void host2guc_slpc(struct intel_slpc *slpc,
>> + struct slpc_event_input *input, u32 len)
>> +{
>> + struct intel_guc *guc = slpc_to_guc(slpc);
>> + u32 *data;
>> + u32 output[SLPC_EVENT_MAX_OUTPUT_ARGS];
>> + int ret = 0;
>> +
>> + /*
>> + * We have only 15 scratch registers for communication.
>> + * the first we will use for the event ID in input and
>> + * output data. Event processing status will be present
>> + * in SOFT_SCRATCH(1) register.
>> + */
>> + BUILD_BUG_ON(SLPC_EVENT_MAX_INPUT_ARGS > 14);
>> + BUILD_BUG_ON(SLPC_EVENT_MAX_OUTPUT_ARGS < 1);
>> + BUILD_BUG_ON(SLPC_EVENT_MAX_OUTPUT_ARGS > 14);
>> +
>> + data = (u32 *) input;
>> + data[0] = INTEL_GUC_ACTION_SLPC_REQUEST;
>> + ret = __intel_guc_send_mmio(guc, data, len, output);
>> +
>> + if (ret)
>> + DRM_ERROR("event 0x%x status %d\n",
>> + ((output[0] & 0xFF00) >> 8), ret);
>> +}
>> +
>> +static void host2guc_slpc_set_param(struct intel_slpc *slpc,
>> + u32 id, u32 value)
>> +{
>> + struct slpc_event_input data = {0};
>> +
>> + data.header.value = SLPC_EVENT(SLPC_EVENT_PARAMETER_SET, 2);
>> + data.args[0] = id;
>> + data.args[1] = value;
>> +
>> + host2guc_slpc(slpc, &data, 4);
>> +}
>> +
>> +static void host2guc_slpc_unset_param(struct intel_slpc *slpc,
>> + u32 id)
>> +{
>> + struct slpc_event_input data = {0};
>> +
>> + data.header.value = SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 1);
>> + data.args[0] = id;
>> +
>> + host2guc_slpc(slpc, &data, 3);
>> +}
>> +
>> +void intel_slpc_set_param(struct intel_slpc *slpc,
>> + u32 id,
>> + u32 value)
>> +{
>> + struct page *page;
>> + struct slpc_shared_data *data = NULL;
>> +
>> + WARN_ON(id >= SLPC_MAX_PARAM);
>> +
>> + if (!slpc->vma)
>> + return;
>> +
>> + page = i915_vma_first_page(slpc->vma);
>> + data = kmap_atomic(page);
>> + slpc_mem_set_param(data, id, value);
>> + kunmap_atomic(data);
>> +
>> + host2guc_slpc_set_param(slpc, id, value);
>> +}
>> +
>> +void intel_slpc_unset_param(struct intel_slpc *slpc,
>> + u32 id)
>> +{
>> + struct page *page;
>> + struct slpc_shared_data *data = NULL;
>> +
>> + WARN_ON(id >= SLPC_MAX_PARAM);
>> +
>> + if (!slpc->vma)
>> + return;
>> +
>> + page = i915_vma_first_page(slpc->vma);
>> + data = kmap_atomic(page);
>> + slpc_mem_unset_param(data, id);
>> + kunmap_atomic(data);
>> +
>> + host2guc_slpc_unset_param(slpc, id);
>> +}
>> +
>> +void intel_slpc_get_param(struct intel_slpc *slpc,
>> + u32 id,
>> + int *overriding, u32 *value)
>> +{
>> + struct page *page;
>> + struct slpc_shared_data *data = NULL;
>> + u32 bits;
>> +
>> + WARN_ON(id >= SLPC_MAX_PARAM);
>> +
>> + if (!slpc->vma)
>> + return;
>> +
>> + page = i915_vma_first_page(slpc->vma);
>> + data = kmap_atomic(page);
>> + if (overriding) {
>> + bits = data->override_parameters_set_bits[id >> 5];
>> + *overriding = (0 != (bits & (1 << (id % 32))));
>> + }
>> + if (value)
>> + *value = data->override_parameters_values[id];
>> +
>> + kunmap_atomic(data);
>> +}
>> +
>> +int intel_slpc_task_control(struct intel_slpc *slpc, u64 val,
>> + u32 enable_id, u32 disable_id)
>> +{
>> + struct drm_i915_private *dev_priv = slpc_to_i915(slpc);
>> + int ret = 0;
>> +
>> + if (!slpc->active)
>> + return -ENODEV;
>> +
>> + intel_runtime_pm_get(dev_priv);
>> +
>> + if (val == SLPC_PARAM_TASK_DEFAULT) {
>> + /* set default */
>> + intel_slpc_unset_param(slpc, enable_id);
>> + intel_slpc_unset_param(slpc, disable_id);
>> + } else if (val == SLPC_PARAM_TASK_ENABLED) {
>> + /* set enable */
>> + intel_slpc_set_param(slpc, enable_id, 1);
>> + intel_slpc_unset_param(slpc, disable_id);
>> + } else if (val == SLPC_PARAM_TASK_DISABLED) {
>> + /* set disable */
>> + intel_slpc_set_param(slpc, disable_id, 1);
>> + intel_slpc_unset_param(slpc, enable_id);
>> + } else {
>> + ret = -EINVAL;
>> + }
>> +
>> + intel_slpc_enable(slpc);
>> + intel_runtime_pm_put(dev_priv);
>> +
>> + return ret;
>> +}
>> +
>> +int intel_slpc_task_status(struct intel_slpc *slpc, u64 *val,
>> + u32 enable_id, u32 disable_id)
>> +{
>> + int override_enable, override_disable;
>> + u32 value_enable, value_disable;
>> + int ret = 0;
>> +
>> + if (!slpc->active) {
>> + ret = -ENODEV;
>> + } else if (val) {
>> + intel_slpc_get_param(slpc, enable_id, &override_enable,
>> + &value_enable);
>> + intel_slpc_get_param(slpc, disable_id, &override_disable,
>> + &value_disable);
>> +
>> + /*
>> + * Set the output value:
>> + * 0: default
>> + * 1: enabled
>> + * 2: disabled
>> + * 3: unknown (should not happen)
>> + */
>> + if (override_disable && (value_disable == 1))
>> + *val = SLPC_PARAM_TASK_DISABLED;
>> + else if (override_enable && (value_enable == 1))
>> + *val = SLPC_PARAM_TASK_ENABLED;
>> + else if (!override_enable && !override_disable)
>> + *val = SLPC_PARAM_TASK_DEFAULT;
>> + else
>> + *val = SLPC_PARAM_TASK_UNKNOWN;
>> +
>> + } else {
>> + ret = -EINVAL;
>> + }
>> +
>> + return ret;
>> +}
>> +
>> static void slpc_shared_data_init(struct intel_slpc *slpc)
>> {
>> struct drm_i915_private *dev_priv = slpc_to_i915(slpc);
>> diff --git a/drivers/gpu/drm/i915/intel_slpc.h
>> b/drivers/gpu/drm/i915/intel_slpc.h
>> index 9312b2f..0ff17f0 100644
>> --- a/drivers/gpu/drm/i915/intel_slpc.h
>> +++ b/drivers/gpu/drm/i915/intel_slpc.h
>> @@ -247,6 +247,14 @@ struct slpc_param {
>> #define SLPC_PARAM_TASK_UNKNOWN 3
>> /* intel_slpc.c */
>> +void intel_slpc_set_param(struct intel_slpc *slpc, u32 id, u32 value);
>> +void intel_slpc_unset_param(struct intel_slpc *slpc, u32 id);
>> +void intel_slpc_get_param(struct intel_slpc *slpc, u32 id,
>> + int *overriding, u32 *value);
>> +int intel_slpc_task_control(struct intel_slpc *slpc, u64 val,
>> + u32 enable_id, u32 disable_id);
>> +int intel_slpc_task_status(struct intel_slpc *slpc, u64 *val,
>> + u32 enable_id, u32 disable_id);
>> void intel_slpc_init(struct intel_slpc *slpc);
>> void intel_slpc_cleanup(struct intel_slpc *slpc);
>> void intel_slpc_enable(struct intel_slpc *slpc);
More information about the Intel-gfx
mailing list