Re: [PATCH 02/14] drm/i915/guc/slpc: Initial definitions for SLPC
On 21.07.2021 18:11, Vinay Belgaumkar wrote: > Add macros to check for SLPC support. This feature is currently supported > for Gen12+ and enabled whenever GuC submission is enabled/selected. > > Include templates for SLPC init/fini and enable. > > v2: Move SLPC helper functions to intel_guc_slpc.c/.h. Define basic > template for SLPC structure in intel_guc_slpc_types.h. Fix copyright (Michal > W) > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > Signed-off-by: Daniele Ceraolo Spurio > > drm/i915/guc/slpc: Lay out slpc init/enable/fini > > Declare init/fini and enable function templates. > > v2: Rebase > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > drivers/gpu/drm/i915/Makefile | 1 + > drivers/gpu/drm/i915/gt/uc/intel_guc.c| 2 + > drivers/gpu/drm/i915/gt/uc/intel_guc.h| 4 ++ > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 63 +++ > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 33 ++ > .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 15 + > drivers/gpu/drm/i915/gt/uc/intel_uc.c | 6 +- > drivers/gpu/drm/i915/gt/uc/intel_uc.h | 2 + > 8 files changed, 124 insertions(+), 2 deletions(-) > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile > index ab7679957623..d8eac4468df9 100644 > --- a/drivers/gpu/drm/i915/Makefile > +++ b/drivers/gpu/drm/i915/Makefile > @@ -186,6 +186,7 @@ i915-y += gt/uc/intel_uc.o \ > gt/uc/intel_guc_fw.o \ > gt/uc/intel_guc_log.o \ > gt/uc/intel_guc_log_debugfs.o \ > + gt/uc/intel_guc_slpc.o \ > gt/uc/intel_guc_submission.o \ > gt/uc/intel_huc.o \ > gt/uc/intel_huc_debugfs.o \ > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > index 979128e28372..39bc3c16057b 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > @@ -7,6 +7,7 @@ > #include "gt/intel_gt_irq.h" > #include "gt/intel_gt_pm_irq.h" > #include "intel_guc.h" > +#include "intel_guc_slpc.h" > #include "intel_guc_ads.h" > #include "intel_guc_submission.h" > #include "i915_drv.h" > @@ -157,6 +158,7 @@ void intel_guc_init_early(struct intel_guc *guc) > intel_guc_ct_init_early(&guc->ct); > intel_guc_log_init_early(&guc->log); > intel_guc_submission_init_early(guc); > + intel_guc_slpc_init_early(&guc->slpc); > > mutex_init(&guc->send_mutex); > spin_lock_init(&guc->irq_lock); > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > index 9c62c68fb132..8cecfad9d7b1 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > @@ -15,6 +15,7 @@ > #include "intel_guc_ct.h" > #include "intel_guc_log.h" > #include "intel_guc_reg.h" > +#include "intel_guc_slpc_types.h" > #include "intel_uc_fw.h" > #include "i915_utils.h" > #include "i915_vma.h" > @@ -30,6 +31,7 @@ struct intel_guc { > struct intel_uc_fw fw; > struct intel_guc_log log; > struct intel_guc_ct ct; > + struct intel_guc_slpc slpc; > > /* Global engine used to submit requests to GuC */ > struct i915_sched_engine *sched_engine; > @@ -57,6 +59,8 @@ struct intel_guc { > > bool submission_supported; > bool submission_selected; > + bool slpc_supported; > + bool slpc_selected; > > struct i915_vma *ads_vma; > struct __guc_ads_blob *ads_blob; > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > new file mode 100644 > index ..d9feb430ce35 > --- /dev/null > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -0,0 +1,63 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright © 2021 Intel Corporation > + */ > + > +#include "i915_drv.h" > +#include "intel_guc_slpc.h" > +#include "gt/intel_gt.h" > + > +static inline struct intel_guc *slpc_to_guc(struct intel_guc_slpc *slpc) > +{ > + return container_of(slpc, struct intel_guc, slpc); > +} > + > +static bool __detect_slpc_supported(struct intel_guc *guc) > +{ > + /* GuC SLPC is unavailable for pre-Gen12 */ > + return guc->submission_supported && > + GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12; > +} > + > +static bool __guc_slpc_selected(struct intel_guc *guc) > +{ > + if (!intel_guc_slpc_is_supported(guc)) > + return false; > + > + return guc->submission_selected; > +} > + > +void intel_guc_slpc_init_early(struct intel_guc_slpc *slpc) > +{ > + struct intel_guc *guc = slpc_to_guc(slpc); > + > + guc->slpc_supported = __detect_slpc_supported(guc); > + guc->slpc_selected = __guc_slpc_sele
Re: [PATCH 04/14] drm/i915/guc/slpc: Adding SLPC communication interfaces
On 21.07.2021 18:11, Vinay Belgaumkar wrote: > Add constants and params that are needed to configure SLPC. > > v2: Add a new abi header for SLPC. Replace bitfields with > genmasks. Address other comments from Michal W. > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > .../drm/i915/gt/uc/abi/guc_actions_slpc_abi.h | 201 ++ > drivers/gpu/drm/i915/gt/uc/intel_guc.c| 4 + > drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 1 + > 3 files changed, 206 insertions(+) > create mode 100644 drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h > > diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h > b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h > new file mode 100644 > index ..05d809746b32 > --- /dev/null > +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h > @@ -0,0 +1,201 @@ > +/* SPDX-License-Identifier: MIT */ > +/* > + * Copyright © 2021 Intel Corporation > + */ > + > +#ifndef _GUC_ACTIONS_SLPC_ABI_H_ > +#define _GUC_ACTIONS_SLPC_ABI_H_ > + > +#include > + > +/** > + * SLPC SHARED DATA STRUCTURE if you want to use kernel-doc, then add DOC: tag > + * > + * > +---+---+--+ > + * | CL| Bytes | Description > | > + * > +===+===+==+ > + * | 1 | 0-3 | SHARED DATA SIZE > | > + * | > +---+--+ > + * | | 4-7 | GLOBAL STATE > | > + * | > +---+--+ > + * | | 8-11 | DISPLAY DATA ADDRESS > | > + * | > +---+--+ > + * | | 12:63 | PADDING > | > + * > +---+---+--+ > + * | | 0:63 | PADDING(PLATFORM INFO) > | > + * > +---+---+--+ > + * | 3 | 0-3 | TASK STATE DATA > | > + * + > +---+--+ > + * | | 4:63 | PADDING > | > + * > +---+---+--+ > + * |4-21 0:1087| OVERRIDE PARAMS AND BIT FIELDS > | ^ something didn't work here > + * > +---+---+--+ > + * | | | PADDING + EXTRA RESERVED PAGE > | > + * > +---+---+--+ > + */ > + > +/* > + * SLPC exposes certain parameters for global configuration by the host. > + * These are referred to as override parameters, because in most cases > + * the host will not need to modify the default values used by SLPC. > + * SLPC remembers the default values which allows the host to easily restore > + * them by simply unsetting the override. The host can set or unset override > + * parameters during SLPC (re-)initialization using the SLPC Reset event. > + * The host can also set or unset override parameters on the fly using the > + * Parameter Set and Parameter Unset events > + */ > + > +#define SLPC_MAX_OVERRIDE_PARAMETERS 256 > +#define SLPC_OVERRIDE_BITFIELD_SIZE \ > + (SLPC_MAX_OVERRIDE_PARAMETERS / 32) > + > +#define SLPC_PAGE_SIZE_BYTES 4096 > +#define SLPC_CACHELINE_SIZE_BYTES64 > +#define SLPC_SHARED_DATA_SIZE_BYTE_HEADERSLPC_CACHELINE_SIZE_BYTES > +#define SLPC_SHARED_DATA_SIZE_BYTE_PLATFORM_INFO > SLPC_CACHELINE_SIZE_BYTES > +#define SLPC_SHARED_DATA_SIZE_BYTE_TASK_STATE > SLPC_CACHELINE_SIZE_BYTES > +#define SLPC_SHARED_DATA_MODE_DEFN_TABLE_SIZESLPC_PAGE_SIZE_BYTES > +#define SLPC_SHARED_DATA_SIZE_BYTE_MAX (2 * > SLPC_PAGE_SIZE_BYTES) > +#define SLPC_EVENT(id, argc) ((u32)(id) << 8 | (argc)) > +#define SLPC_EVENT_MAX_INPUT_ARGS9 above two are likely used in H2G SLPC message that is not fully defined, maybe at the end of this file add separate section with H2G format, using plain C #defines, and move SLPC_EVENT helper macro to fwif.h > + > +/* > + * Cacheline size aligned (Total size needed for > + * SLPM_KMD_MAX_OVERRIDE_PARAMETERS=256 is 1088 bytes) > + */ > +#define SLPC_OVERRIDE_PARAMS_TOTAL_BYTES > (SLPC_MAX_OVERRIDE_PARAMETERS * 4) \ > + + > ((SLPC_MAX_OVERRIDE_PARAMETERS / 32) * 4)) \ > + + (SLPC_CAC
Re: [Intel-gfx] [PATCH 05/14] drm/i915/guc/slpc: Allocate, initialize and release SLPC
On 21.07.2021 18:11, Vinay Belgaumkar wrote: > Allocate data structures for SLPC and functions for > initializing on host side. > > v2: Address review comments (Michal W) > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > drivers/gpu/drm/i915/gt/uc/intel_guc.c| 11 ++ > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 36 ++- > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 1 + > .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 3 ++ > 4 files changed, 50 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > index fcccb103a21a..686cb978662d 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > @@ -337,6 +337,12 @@ int intel_guc_init(struct intel_guc *guc) > goto err_ct; > } > > + if (intel_guc_slpc_is_used(guc)) { > + ret = intel_guc_slpc_init(&guc->slpc); > + if (ret) > + goto err_submission; > + } > + > /* now that everything is perma-pinned, initialize the parameters */ > guc_init_params(guc); > > @@ -347,6 +353,8 @@ int intel_guc_init(struct intel_guc *guc) > > return 0; > > +err_submission: > + intel_guc_submission_fini(guc); > err_ct: > intel_guc_ct_fini(&guc->ct); > err_ads: > @@ -369,6 +377,9 @@ void intel_guc_fini(struct intel_guc *guc) > > i915_ggtt_disable_guc(gt->ggtt); > > + if (intel_guc_slpc_is_used(guc)) > + intel_guc_slpc_fini(&guc->slpc); > + > if (intel_guc_submission_is_used(guc)) > intel_guc_submission_fini(guc); > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index d9feb430ce35..a99d727b5bf0 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -12,6 +12,16 @@ static inline struct intel_guc *slpc_to_guc(struct > intel_guc_slpc *slpc) > return container_of(slpc, struct intel_guc, slpc); > } > > +static inline struct intel_gt *slpc_to_gt(struct intel_guc_slpc *slpc) > +{ > + return guc_to_gt(slpc_to_guc(slpc)); > +} > + > +static inline struct drm_i915_private *slpc_to_i915(struct intel_guc_slpc > *slpc) > +{ > + return (slpc_to_gt(slpc))->i915; redundant ( ) > +} > + > static bool __detect_slpc_supported(struct intel_guc *guc) > { > /* GuC SLPC is unavailable for pre-Gen12 */ > @@ -35,9 +45,29 @@ void intel_guc_slpc_init_early(struct intel_guc_slpc *slpc) > guc->slpc_selected = __guc_slpc_selected(guc); > } > > +static int slpc_shared_data_init(struct intel_guc_slpc *slpc) > +{ > + struct intel_guc *guc = slpc_to_guc(slpc); > + struct drm_i915_private *i915 = slpc_to_i915(slpc); > + u32 size = PAGE_ALIGN(sizeof(struct slpc_shared_data)); > + int err; > + > + err = intel_guc_allocate_and_map_vma(guc, size, &slpc->vma, (void > **)&slpc->vaddr); > + if (unlikely(err)) { > + drm_err(&i915->drm, > + "Failed to allocate SLPC struct (err=%pe)\n", > + ERR_PTR(err)); > + return err; > + } > + > + return err; > +} > + > int intel_guc_slpc_init(struct intel_guc_slpc *slpc) > { > - return 0; > + GEM_BUG_ON(slpc->vma); > + > + return slpc_shared_data_init(slpc); > } > > /* > @@ -60,4 +90,8 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) > > void intel_guc_slpc_fini(struct intel_guc_slpc *slpc) > { > + if (!slpc->vma) > + return; > + > + i915_vma_unpin_and_release(&slpc->vma, I915_VMA_RELEASE_MAP); > } > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > index c3b0ad7f0f93..f02249ff5f1b 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > @@ -8,6 +8,7 @@ > > #include "intel_guc_submission.h" > #include "intel_guc_slpc_types.h" > +#include "abi/guc_actions_slpc_abi.h" is this is needed here ? maybe abi.h could be included only in slcp.c ? > > static inline bool intel_guc_slpc_is_supported(struct intel_guc *guc) > { > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > index b85148265b1f..214a449e78f2 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > @@ -7,9 +7,12 @@ > #define _INTEL_GUC_SLPC_TYPES_H_ > > #include > +#include "abi/guc_actions_slpc_abi.h" for below pointers you don't need this header(s) to be included Michal > > struct intel_guc_slpc { > > + struct i915_vma *vma; > + struct slpc_shared_data *vaddr; > }; > > #endif >
Re: [Intel-gfx] [PATCH 07/16] drm/i915/guc/slpc: Enable slpc and add related H2G events
On 15.07.2021 03:58, Belgaumkar, Vinay wrote: > > > On 7/10/2021 10:37 AM, Michal Wajdeczko wrote: >> >> >> On 10.07.2021 03:20, Vinay Belgaumkar wrote: ... >>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c >>> b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c >>> index e2644a05f298..3e76d4d5f7bb 100644 >>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c >>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c >>> @@ -2321,10 +2321,6 @@ void intel_guc_submission_enable(struct >>> intel_guc *guc) >>> void intel_guc_submission_disable(struct intel_guc *guc) >>> { >>> - struct intel_gt *gt = guc_to_gt(guc); >>> - >>> - GEM_BUG_ON(gt->awake); /* GT should be parked first */ >> >> if not mistake, can you explain why it was removed ? > > This was part of a different commit. The BUG_ON in > disable_guc_submission was added with an assumption that it will be > called only during driver unload and not expected to hold any GT PM > references. Since this needs to be called from an error scenario during > slpc enable, remove the BUG_ON. Do we need this as a separate commit? yes, please Michal
Re: [PATCH 06/14] drm/i915/guc/slpc: Enable SLPC and add related H2G events
On 21.07.2021 18:11, Vinay Belgaumkar wrote: > Add methods for interacting with GuC for enabling SLPC. Enable > SLPC after GuC submission has been established. GuC load will > fail if SLPC cannot be successfully initialized. Add various > helper methods to set/unset the parameters for SLPC. They can > be set using H2G calls or directly setting bits in the shared > data structure. > > This patch also removes the GEM_BUG_ON from guc_submission_disable(). > The assumption when that was added was there would be no wakerefs > when it would be called. However, if we fail to enable slpc, we will s/slpc/SLPC > still be holding a wakeref. > > v2: Address several review comments, add new helpers for > decoding the slpc min/max frequencies. Use masks instead of hardcoded > constants. (Michal W) > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 206 ++ > .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 2 + > .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 4 - > drivers/gpu/drm/i915/gt/uc/intel_uc.c | 10 + > 4 files changed, 218 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index a99d727b5bf0..48db2a8f67d1 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -45,6 +45,40 @@ void intel_guc_slpc_init_early(struct intel_guc_slpc *slpc) > guc->slpc_selected = __guc_slpc_selected(guc); > } > > +static void slpc_mem_set_param(struct slpc_shared_data *data, > + u32 id, u32 value) > +{ > + GEM_BUG_ON(id >= SLPC_MAX_OVERRIDE_PARAMETERS); > + /* > + * When the flag bit is set, corresponding value will be read > + * and applied by slpc. > + */ > + data->override_params.bits[id >> 5] |= (1 << (id % 32)); > + data->override_params.values[id] = value; > +} > + > +static void slpc_mem_set_enabled(struct slpc_shared_data *data, > + u8 enable_id, u8 disable_id) > +{ > + /* > + * Enabling a param involves setting the enable_id > + * to 1 and disable_id to 0. > + */ > + slpc_mem_set_param(data, enable_id, 1); > + slpc_mem_set_param(data, disable_id, 0); > +} > + > +static void slpc_mem_set_disabled(struct slpc_shared_data *data, > + u8 enable_id, u8 disable_id) > +{ > + /* > + * Disabling a param involves setting the enable_id > + * to 0 and disable_id to 1. > + */ > + slpc_mem_set_param(data, disable_id, 1); > + slpc_mem_set_param(data, enable_id, 0); > +} > + > static int slpc_shared_data_init(struct intel_guc_slpc *slpc) > { > struct intel_guc *guc = slpc_to_guc(slpc); > @@ -63,6 +97,116 @@ static int slpc_shared_data_init(struct intel_guc_slpc > *slpc) > return err; > } > > +static u32 slpc_get_state(struct intel_guc_slpc *slpc) > +{ > + struct slpc_shared_data *data; > + > + GEM_BUG_ON(!slpc->vma); > + > + drm_clflush_virt_range(slpc->vaddr, sizeof(u32)); > + data = slpc->vaddr; > + > + return data->header.global_state; > +} > + > +static bool slpc_is_running(struct intel_guc_slpc *slpc) > +{ > + return (slpc_get_state(slpc) == SLPC_GLOBAL_STATE_RUNNING); > +} > + > +static int guc_action_slpc_query(struct intel_guc *guc, u32 offset) > +{ > + u32 request[] = { > + INTEL_GUC_ACTION_SLPC_REQUEST, > + SLPC_EVENT(SLPC_EVENT_QUERY_TASK_STATE, 2), > + offset, > + 0, > + }; > + > + return intel_guc_send(guc, request, ARRAY_SIZE(request)); > +} > + > +static int slpc_query_task_state(struct intel_guc_slpc *slpc) > +{ > + struct intel_guc *guc = slpc_to_guc(slpc); > + struct drm_i915_private *i915 = slpc_to_i915(slpc); > + u32 shared_data_gtt_offset = intel_guc_ggtt_offset(guc, slpc->vma); > + int ret; > + > + ret = guc_action_slpc_query(guc, shared_data_gtt_offset); > + if (ret) > + drm_err(&i915->drm, "Query task state data returned (%pe)\n", > + ERR_PTR(ret)); > + > + drm_clflush_virt_range(slpc->vaddr, SLPC_PAGE_SIZE_BYTES); > + > + return ret; > +} > + > +static const char *slpc_state_string(struct intel_guc_slpc *slpc) > +{ > + const char *str = NULL; > + u32 state = slpc_get_state(slpc); > + > + switch (state) { > + case SLPC_GLOBAL_STATE_NOT_RUNNING: > + str = "not running"; > + break; > + case SLPC_GLOBAL_STATE_INITIALIZING: > + str = "initializing"; > + break; > + case SLPC_GLOBAL_STATE_RESETTING: > + str = "resetting"; > + break; > + case SLPC_GLOBAL_STATE_RUNNING: > + str = "running"; > + break; > + case SLPC_GLOBAL_STATE_SHUTTING_DOWN: > + str = "shutting down"; > +
Re: [PATCH 07/14] drm/i915/guc/slpc: Add methods to set min/max frequency
On 21.07.2021 18:11, Vinay Belgaumkar wrote: > Add param set h2g helpers to set the min and max frequencies > for use by SLPC. > > v2: Address review comments (Michal W) > > Signed-off-by: Sundaresan Sujaritha > Signed-off-by: Vinay Belgaumkar > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 84 + > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 2 + > 2 files changed, 86 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index 48db2a8f67d1..b40c39ba4049 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -109,6 +109,18 @@ static u32 slpc_get_state(struct intel_guc_slpc *slpc) > return data->header.global_state; > } > > +static int guc_action_slpc_set_param(struct intel_guc *guc, u8 id, u32 value) > +{ > + u32 request[] = { > + INTEL_GUC_ACTION_SLPC_REQUEST, > + SLPC_EVENT(SLPC_EVENT_PARAMETER_SET, 2), > + id, > + value, > + }; > + > + return intel_guc_send(guc, request, ARRAY_SIZE(request)); beware of possible non-zero data0 returned by guc_send() > +} > + > static bool slpc_is_running(struct intel_guc_slpc *slpc) > { > return (slpc_get_state(slpc) == SLPC_GLOBAL_STATE_RUNNING); > @@ -143,6 +155,15 @@ static int slpc_query_task_state(struct intel_guc_slpc > *slpc) > return ret; > } > > +static int slpc_set_param(struct intel_guc_slpc *slpc, u8 id, u32 value) > +{ > + struct intel_guc *guc = slpc_to_guc(slpc); > + > + GEM_BUG_ON(id >= SLPC_MAX_PARAM); > + > + return guc_action_slpc_set_param(guc, id, value); > +} > + > static const char *slpc_state_string(struct intel_guc_slpc *slpc) > { > const char *str = NULL; > @@ -238,6 +259,69 @@ u32 slpc_decode_max_freq(struct intel_guc_slpc *slpc) > GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER); > } > > +/** > + * intel_guc_slpc_set_max_freq() - Set max frequency limit for SLPC. > + * @slpc: pointer to intel_guc_slpc. > + * @val: frequency (MHz) > + * > + * This function will invoke GuC SLPC action to update the max frequency > + * limit for unslice. > + * > + * Return: 0 on success, non-zero error code on failure. > + */ > +int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val) > +{ > + int ret; > + struct drm_i915_private *i915 = slpc_to_i915(slpc); > + intel_wakeref_t wakeref; nit: move "ret" as last > + > + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { > + ret = slpc_set_param(slpc, > +SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ, > +val); > + if (ret) { > + drm_err(&i915->drm, > + "Set max frequency unslice returned (%pe)\n", > ERR_PTR(ret)); > + /* Return standardized err code for sysfs */ > + ret = -EIO; maybe caller (hook in sysfs) can sanitize this error ? Michal > + } > + } > + > + return ret; > +} > + > +/** > + * intel_guc_slpc_set_min_freq() - Set min frequency limit for SLPC. > + * @slpc: pointer to intel_guc_slpc. > + * @val: frequency (MHz) > + * > + * This function will invoke GuC SLPC action to update the min unslice > + * frequency. > + * > + * Return: 0 on success, non-zero error code on failure. > + */ > +int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val) > +{ > + int ret; > + struct intel_guc *guc = slpc_to_guc(slpc); > + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; > + intel_wakeref_t wakeref; > + > + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { > + ret = slpc_set_param(slpc, > +SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ, > +val); > + if (ret) { > + drm_err(&i915->drm, > + "Set min frequency for unslice returned > (%pe)\n", ERR_PTR(ret)); > + /* Return standardized err code for sysfs */ > + ret = -EIO; > + } > + } > + > + return ret; > +} > + > /* > * intel_guc_slpc_enable() - Start SLPC > * @slpc: pointer to intel_guc_slpc. > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > index f02249ff5f1b..3a1a7eaafc12 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > @@ -30,5 +30,7 @@ void intel_guc_slpc_init_early(struct intel_guc_slpc *slpc); > int intel_guc_slpc_init(struct intel_guc_slpc *slpc); > int intel_guc_slpc_enable(struct intel_guc_slpc *slpc); > void intel_guc_slpc_fini(struct intel_guc_slpc *slpc); > +int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val); > +int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val); > > #endif >
Re: [PATCH 08/14] drm/i915/guc/slpc: Add get max/min freq hooks
On 21.07.2021 18:11, Vinay Belgaumkar wrote: > Add helpers to read the min/max frequency being used > by SLPC. This is done by send a H2G command which forces > SLPC to update the shared data struct which can then be > read. add note that functions will be used later > > v2: Address review comments (Michal W) > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 52 + > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 2 + > 2 files changed, 54 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index b40c39ba4049..c1cf8d46e360 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -290,6 +290,32 @@ int intel_guc_slpc_set_max_freq(struct intel_guc_slpc > *slpc, u32 val) > return ret; > } > > +/** > + * intel_guc_slpc_get_max_freq() - Get max frequency limit for SLPC. > + * @slpc: pointer to intel_guc_slpc. > + * @val: pointer to val which will hold max frequency (MHz) > + * > + * This function will invoke GuC SLPC action to read the max frequency > + * limit for unslice. > + * > + * Return: 0 on success, non-zero error code on failure. > + */ > +int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val) > +{ > + intel_wakeref_t wakeref; > + struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915; > + int ret = 0; struct drm_i915_private *i915 = slpc_to_i915(slpc); intel_wakeref_t wakeref; int ret = 0; > + > + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { > + /* Force GuC to update task data */ > + slpc_query_task_state(slpc); what if this call fails ? > + > + *val = slpc_decode_max_freq(slpc); > + } > + > + return ret; > +} > + > /** > * intel_guc_slpc_set_min_freq() - Set min frequency limit for SLPC. > * @slpc: pointer to intel_guc_slpc. > @@ -322,6 +348,32 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc > *slpc, u32 val) > return ret; > } > > +/** > + * intel_guc_slpc_get_min_freq() - Get min frequency limit for SLPC. > + * @slpc: pointer to intel_guc_slpc. > + * @val: pointer to val which will hold min frequency (MHz) > + * > + * This function will invoke GuC SLPC action to read the min frequency > + * limit for unslice. > + * > + * Return: 0 on success, non-zero error code on failure. > + */ > +int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val) > +{ > + intel_wakeref_t wakeref; > + struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915; > + int ret = 0; > + > + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { > + /* Force GuC to update task data */ > + slpc_query_task_state(slpc); same here Michal > + > + *val = slpc_decode_min_freq(slpc); > + } > + > + return ret; > +} > + > /* > * intel_guc_slpc_enable() - Start SLPC > * @slpc: pointer to intel_guc_slpc. > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > index 3a1a7eaafc12..627c71a95777 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > @@ -32,5 +32,7 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc); > void intel_guc_slpc_fini(struct intel_guc_slpc *slpc); > int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val); > int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val); > +int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val); > +int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val); > > #endif >
Re: [PATCH 09/14] drm/i915/guc/slpc: Add debugfs for SLPC info
On 21.07.2021 18:11, Vinay Belgaumkar wrote: > This prints out relevant SLPC info from the SLPC shared structure. > > We will send a h2g message which forces SLPC to update the > shared data structure with latest information before reading it. > > v2: Address review comments (Michal W) > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > .../gpu/drm/i915/gt/uc/intel_guc_debugfs.c| 23 +++ > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 40 +++ > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 4 +- > 3 files changed, 66 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c > index 72ddfff42f7d..46b22187927b 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c > @@ -12,6 +12,7 @@ > #include "gt/uc/intel_guc_ct.h" > #include "gt/uc/intel_guc_ads.h" > #include "gt/uc/intel_guc_submission.h" > +#include "gt/uc/intel_guc_slpc.h" > > static int guc_info_show(struct seq_file *m, void *data) > { > @@ -50,11 +51,33 @@ static int guc_registered_contexts_show(struct seq_file > *m, void *data) > } > DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_registered_contexts); > > +static int guc_slpc_info_show(struct seq_file *m, void *unused) > +{ > + struct intel_guc *guc = m->private; > + struct intel_guc_slpc *slpc = &guc->slpc; > + struct drm_printer p = drm_seq_file_printer(m); > + > + if (!intel_guc_slpc_is_used(guc)) > + return -ENODEV; > + > + return intel_guc_slpc_info(slpc, &p); > +} > +DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_slpc_info); > + > +bool intel_eval_slpc_support(void *data) > +{ > + struct intel_guc *guc; > + > + guc = (struct intel_guc *)data; struct intel_guc *guc = (struct intel_guc *)data; > + return intel_guc_slpc_is_used(guc); > +} > + > void intel_guc_debugfs_register(struct intel_guc *guc, struct dentry *root) > { > static const struct debugfs_gt_file files[] = { > { "guc_info", &guc_info_fops, NULL }, > { "guc_registered_contexts", &guc_registered_contexts_fops, > NULL }, > + { "guc_slpc_info", &guc_slpc_info_fops, > &intel_eval_slpc_support}, > }; > > if (!intel_guc_is_supported(guc)) > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index c1cf8d46e360..73379985c105 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -430,6 +430,46 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) > return 0; > } > > +int intel_guc_slpc_info(struct intel_guc_slpc *slpc, struct drm_printer *p) > +{ > + struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915; > + struct slpc_shared_data *data; > + struct slpc_task_state_data *slpc_tasks; > + intel_wakeref_t wakeref; > + int ret = 0; > + > + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { > + if (slpc_query_task_state(slpc)) > + return -EIO; not sure if you can return directly from "with_rpm" > + > + slpc_tasks = &data->task_state_data; > + > + drm_printf(p, "SLPC state: %s\n", slpc_state_string(slpc)); > + drm_printf(p, "\tgtperf task active: %s\n", > + yesno(slpc_tasks->status & SLPC_GTPERF_TASK_ACTIVE)); > + drm_printf(p, "\tdcc task active: %s\n", > + yesno(slpc_tasks->status & SLPC_DCC_TASK_ACTIVE)); > + drm_printf(p, "\tin dcc: %s\n", > + yesno(slpc_tasks->status & SLPC_IN_DCC)); > + drm_printf(p, "\tfreq switch active: %s\n", > + yesno(slpc_tasks->status & SLPC_FREQ_SWITCH_ACTIVE)); > + drm_printf(p, "\tibc enabled: %s\n", > + yesno(slpc_tasks->status & SLPC_IBC_ENABLED)); > + drm_printf(p, "\tibc active: %s\n", > + yesno(slpc_tasks->status & SLPC_IBC_ACTIVE)); > + drm_printf(p, "\tpg1 enabled: %s\n", > + yesno(slpc_tasks->status & SLPC_PG1_ENABLED)); > + drm_printf(p, "\tpg1 active: %s\n", > + yesno(slpc_tasks->status & SLPC_PG1_ACTIVE)); > + drm_printf(p, "\tmax freq: %dMHz\n", > + slpc_decode_max_freq(slpc)); > + drm_printf(p, "\tmin freq: %dMHz\n", > + slpc_decode_min_freq(slpc)); not sure what they are: DCC ? IBC ? PG1 ? and make sure to use %u for unsigned Michal > + } > + > + return ret; > +} > + > void intel_guc_slpc_fini(struct intel_guc_slpc *slpc) > { > if (!slpc->vma) > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > index 627c71a95777..852c6316aa47 100644 > --- a/drivers/gpu/dr
Re: [PATCH 11/14] drm/i915/guc/slpc: Cache platform frequency limits
On 21.07.2021 18:11, Vinay Belgaumkar wrote: > Cache rp0, rp1 and rpn platform limits into SLPC structure > for range checking while setting min/max frequencies. > > Also add "soft" limits which keep track of frequency changes > made from userland. These are initially set to platform min > and max. > > v2: Address review comments (Michal W) > > Signed-off-by: Vinay Belgaumkar > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 98 +++ > .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 9 ++ > drivers/gpu/drm/i915/i915_reg.h | 3 + > 3 files changed, 110 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index 8796a8929d89..134c57ca10b7 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -94,6 +94,9 @@ static int slpc_shared_data_init(struct intel_guc_slpc > *slpc) > return err; > } > > + slpc->max_freq_softlimit = 0; > + slpc->min_freq_softlimit = 0; > + > return err; > } > > @@ -121,6 +124,19 @@ static int guc_action_slpc_set_param(struct intel_guc > *guc, u8 id, u32 value) > return intel_guc_send(guc, request, ARRAY_SIZE(request)); > } > > +static int guc_action_slpc_unset_param(struct intel_guc *guc, > + u8 id) > +{ > + u32 request[] = { > + INTEL_GUC_ACTION_SLPC_REQUEST, > + SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 2), > + id, > + }; > + > + return intel_guc_send(guc, request, ARRAY_SIZE(request)); > +} > + > + > static bool slpc_is_running(struct intel_guc_slpc *slpc) > { > return (slpc_get_state(slpc) == SLPC_GLOBAL_STATE_RUNNING); > @@ -164,6 +180,16 @@ static int slpc_set_param(struct intel_guc_slpc *slpc, > u8 id, u32 value) > return guc_action_slpc_set_param(guc, id, value); > } > > +static int slpc_unset_param(struct intel_guc_slpc *slpc, > + u8 id) likely can fit into one line > +{ > + struct intel_guc *guc = slpc_to_guc(slpc); > + > + GEM_BUG_ON(id >= SLPC_MAX_PARAM); > + > + return guc_action_slpc_unset_param(guc, id); > +} > + > static const char *slpc_state_string(struct intel_guc_slpc *slpc) > { > const char *str = NULL; > @@ -388,6 +414,55 @@ void intel_guc_pm_intrmsk_enable(struct intel_gt *gt) > GEN6_PMINTRMSK, pm_intrmsk_mbz, 0); > } > > +static int intel_guc_slpc_set_softlimits(struct intel_guc_slpc *slpc) > +{ > + int ret = 0; > + > + /* Softlimits are initially equivalent to platform limits > + * unless they have deviated from defaults, in which case, > + * we retain the values and set min/max accordingly. > + */ > + if (!slpc->max_freq_softlimit) > + slpc->max_freq_softlimit = slpc->rp0_freq; > + else if (slpc->max_freq_softlimit != slpc->rp0_freq) > + ret = intel_guc_slpc_set_max_freq(slpc, > + slpc->max_freq_softlimit); > + > + if (!slpc->min_freq_softlimit) > + slpc->min_freq_softlimit = slpc->min_freq; > + else if (slpc->min_freq_softlimit != slpc->min_freq) > + ret = intel_guc_slpc_set_min_freq(slpc, > + slpc->min_freq_softlimit); > + > + return ret; > +} > + > +static void intel_guc_slpc_ignore_eff_freq(struct intel_guc_slpc *slpc, bool > ignore) > +{ > + if (ignore) { > + /* A failure here does not affect the algorithm in a fatal way > */ > + slpc_set_param(slpc, > +SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY, > +ignore); > + slpc_set_param(slpc, > +SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ, > +slpc->min_freq); > + } else { > + slpc_unset_param(slpc, > +SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY); > + slpc_unset_param(slpc, > +SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ); hard to tell from mail client, but likely misalignment did you run checkpatch.pl ? > + } > +} > + > +static void intel_guc_slpc_use_fused_rp0(struct intel_guc_slpc *slpc) > +{ > + /* Force slpc to used platform rp0 */ > + slpc_set_param(slpc, > +SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ, > +slpc->rp0_freq); > +} > + > /* > * intel_guc_slpc_enable() - Start SLPC > * @slpc: pointer to intel_guc_slpc. > @@ -405,6 +480,7 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) > { > struct drm_i915_private *i915 = slpc_to_i915(slpc); > struct slpc_shared_data *data; > + u32 rp_state_cap; > int ret; > > GEM_BUG_ON(!slpc->vma); > @@ -442,6 +518,28 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) > slpc_decode_min_freq(slpc), > slpc_decode_max_freq(slpc)); > > + rp_state_cap =
Re: [PATCH 12/14] drm/i915/guc/slpc: Sysfs hooks for SLPC
cy(rps, val); > > return ret ?: count; > } > @@ -380,9 +354,10 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, > static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct > device_attribute *attr, char *buf) > { > struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); > - struct intel_rps *rps = &dev_priv->gt.rps; > + struct intel_gt *gt = &dev_priv->gt; > + struct intel_rps *rps = >->rps; > > - return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, > rps->min_freq_softlimit)); > + return sysfs_emit(buf, "%d\n", intel_rps_get_min_frequency(rps)); > } > > static ssize_t gt_min_freq_mhz_store(struct device *kdev, > @@ -398,31 +373,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, > if (ret) > return ret; > > - mutex_lock(&rps->lock); > - > - val = intel_freq_opcode(rps, val); > - if (val < rps->min_freq || > - val > rps->max_freq || > - val > rps->max_freq_softlimit) { > - ret = -EINVAL; > - goto unlock; > - } > - > - rps->min_freq_softlimit = val; > - > - val = clamp_t(int, rps->cur_freq, > - rps->min_freq_softlimit, > - rps->max_freq_softlimit); > - > - /* > - * We still need *_set_rps to process the new min_delay and > - * update the interrupt limits and PMINTRMSK even though > - * frequency request may be unchanged. > - */ > - intel_rps_set(rps, val); > - > -unlock: > - mutex_unlock(&rps->lock); > + ret = intel_rps_set_min_frequency(rps, val); > > return ret ?: count; > } > @@ -448,11 +399,11 @@ static ssize_t gt_rp_mhz_show(struct device *kdev, > struct device_attribute *attr > u32 val; > > if (attr == &dev_attr_gt_RP0_freq_mhz) > - val = intel_gpu_freq(rps, rps->rp0_freq); > + val = intel_rps_get_rp0_frequency(rps); > else if (attr == &dev_attr_gt_RP1_freq_mhz) > - val = intel_gpu_freq(rps, rps->rp1_freq); > + val = intel_rps_get_rp1_frequency(rps); > else if (attr == &dev_attr_gt_RPn_freq_mhz) > - val = intel_gpu_freq(rps, rps->min_freq); > + val = intel_rps_get_rpn_frequency(rps); > else > BUG(); > > LGTM, but likely you will want someone who is more familiar with RPS to give r-b, from my side, with typo fixed, this is: Acked-by: Michal Wajdeczko
Re: [PATCH 14/14] drm/i915/guc/rc: Setup and enable GUCRC feature
*guc) > intel_guc_log_init_early(&guc->log); > intel_guc_submission_init_early(guc); > intel_guc_slpc_init_early(&guc->slpc); > + intel_guc_rc_init_early(guc); > > mutex_init(&guc->send_mutex); > spin_lock_init(&guc->irq_lock); > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > index 8cecfad9d7b1..dcac31098687 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > @@ -59,6 +59,8 @@ struct intel_guc { > > bool submission_supported; > bool submission_selected; > + bool rc_supported; > + bool rc_selected; > bool slpc_supported; > bool slpc_selected; > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c > new file mode 100644 > index ..f1970342c0ab > --- /dev/null > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c > @@ -0,0 +1,81 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright © 2021 Intel Corporation > + */ > + > +#include "intel_guc_rc.h" > +#include "gt/intel_gt.h" > +#include "i915_drv.h" > + > +static bool __guc_rc_supported(struct intel_guc *guc) > +{ > + /* GuC RC is unavailable for pre-Gen12 */ > + return guc->submission_supported && > + GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12; > +} > + > +static bool __guc_rc_selected(struct intel_guc *guc) > +{ > + if (!intel_guc_rc_is_supported(guc)) > + return false; > + > + return guc->submission_selected; > +} > + > +void intel_guc_rc_init_early(struct intel_guc *guc) > +{ > + guc->rc_supported = __guc_rc_supported(guc); > + guc->rc_selected = __guc_rc_selected(guc); > +} > + > +static int guc_action_control_gucrc(struct intel_guc *guc, bool enable) > +{ > + u32 rc_mode = enable ? INTEL_GUCRC_FIRMWARE_CONTROL : > + INTEL_GUCRC_HOST_CONTROL; nit: likely can be done directly in array initialization > + u32 action[] = { > + INTEL_GUC_ACTION_SETUP_PC_GUCRC, > + rc_mode > + }; > + int ret; > + > + ret = intel_guc_send(guc, action, ARRAY_SIZE(action)); > + ret = ret > 0 ? -EPROTO : ret; > + > + return ret; > +} > + > +static int __guc_rc_control(struct intel_guc *guc, bool enable) > +{ > + struct intel_gt *gt = guc_to_gt(guc); > + struct drm_device *drm = &guc_to_gt(guc)->i915->drm; > + int ret; > + > + if (!intel_uc_uses_guc_rc(>->uc)) > + return -ENOTSUPP; > + > + if (!intel_guc_is_ready(guc)) > + return -EINVAL; > + > + ret = guc_action_control_gucrc(guc, enable); > + if (ret) { > + drm_err(drm, "Failed to set GUCRC mode(%d), err=(%pe)\n", below you are referring to "GuC RC" so to be consistent: "Failed to %s GuC RC mode (%pe)\n", enabledisable(enable), ERR_PTR(err) with message fixed, Reviewed-by: Michal Wajdeczko > + enable ? INTEL_GUCRC_FIRMWARE_CONTROL: > + INTEL_GUCRC_HOST_CONTROL, ERR_PTR(ret)); > + return ret; > + } > + > + drm_info(>->i915->drm, "GuC RC %s\n", > + enableddisabled(enable)); > + > + return 0; > +} > + > +int intel_guc_rc_enable(struct intel_guc *guc) > +{ > + return __guc_rc_control(guc, true); > +} > + > +int intel_guc_rc_disable(struct intel_guc *guc) > +{ > + return __guc_rc_control(guc, false); > +} > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h > new file mode 100644 > index ..57e86c337838 > --- /dev/null > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h > @@ -0,0 +1,31 @@ > +/* SPDX-License-Identifier: MIT */ > +/* > + * Copyright © 2021 Intel Corporation > + */ > + > +#ifndef _INTEL_GUC_RC_H_ > +#define _INTEL_GUC_RC_H_ > + > +#include "intel_guc_submission.h" > + > +void intel_guc_rc_init_early(struct intel_guc *guc); > + > +static inline bool intel_guc_rc_is_supported(struct intel_guc *guc) > +{ > + return guc->rc_supported; > +} > + > +static inline bool intel_guc_rc_is_wanted(struct intel_guc *guc) > +{ > + return guc->submission_selected && intel_guc_rc_is_supported(guc); > +} > + > +static inline bool intel_guc_rc_is_used(struct intel_guc *guc) > +{ > + return intel_guc_submission_is_used(guc) && intel_guc_rc_is_wanted(guc); > +} > + > +int intel_guc_rc_enable(struct intel_guc *guc); > +int intel_guc_rc_disable(struct intel_guc *guc); > + > +#endif > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.h > b/drivers/gpu/drm/i915/gt/uc/intel_uc.h > index 925a58ca6b94..866b462821c0 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.h > @@ -7,6 +7,7 @@ > #define _INTEL_UC_H_ > > #include "intel_guc.h" > +#include "intel_guc_rc.h" > #include "intel_guc_submission.h" > #include "intel_guc_slpc.h" > #include "intel_huc.h" > @@ -85,6 +86,7 @@ uc_state_checkers(guc, guc); > uc_state_checkers(huc, huc); > uc_state_checkers(guc, guc_submission); > uc_state_checkers(guc, guc_slpc); > +uc_state_checkers(guc, guc_rc); > > #undef uc_state_checkers > #undef __uc_state_checker >
Re: [Intel-gfx] [PATCH 06/51] drm/i915/guc: Implement GuC context operations for new inteface
On 22.07.2021 01:51, Daniele Ceraolo Spurio wrote: > > > On 7/19/2021 9:04 PM, Matthew Brost wrote: >> On Mon, Jul 19, 2021 at 05:51:46PM -0700, Daniele Ceraolo Spurio wrote: >>> >>> On 7/16/2021 1:16 PM, Matthew Brost wrote: Implement GuC context operations which includes GuC specific operations alloc, pin, unpin, and destroy. v2: (Daniel Vetter) - Use msleep_interruptible rather than cond_resched in busy loop (Michal) - Remove C++ style comment Signed-off-by: John Harrison Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/gt/intel_context.c | 5 + drivers/gpu/drm/i915/gt/intel_context_types.h | 22 +- drivers/gpu/drm/i915/gt/intel_lrc_reg.h | 1 - drivers/gpu/drm/i915/gt/uc/intel_guc.h | 40 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 4 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 666 -- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/i915_request.c | 1 + 8 files changed, 685 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index bd63813c8a80..32fd6647154b 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -384,6 +384,11 @@ intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine) mutex_init(&ce->pin_mutex); + spin_lock_init(&ce->guc_state.lock); + + ce->guc_id = GUC_INVALID_LRC_ID; + INIT_LIST_HEAD(&ce->guc_id_link); + i915_active_init(&ce->active, __intel_context_active, __intel_context_retire, 0); } diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 6d99631d19b9..606c480aec26 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -96,6 +96,7 @@ struct intel_context { #define CONTEXT_BANNED 6 #define CONTEXT_FORCE_SINGLE_SUBMISSION 7 #define CONTEXT_NOPREEMPT 8 +#define CONTEXT_LRCA_DIRTY 9 struct { u64 timeout_us; @@ -138,14 +139,29 @@ struct intel_context { u8 wa_bb_page; /* if set, page num reserved for context workarounds */ + struct { + /** lock: protects everything in guc_state */ + spinlock_t lock; + /** + * sched_state: scheduling state of this context using GuC + * submission + */ + u8 sched_state; + } guc_state; + /* GuC scheduling state flags that do not require a lock. */ atomic_t guc_sched_state_no_lock; + /* GuC LRC descriptor ID */ + u16 guc_id; + + /* GuC LRC descriptor reference count */ + atomic_t guc_id_ref; + /* - * GuC LRC descriptor ID - Not assigned in this patch but future patches - * in the series will. + * GuC ID link - in list when unpinned but guc_id still valid in GuC */ - u16 guc_id; + struct list_head guc_id_link; }; #endif /* __INTEL_CONTEXT_TYPES__ */ diff --git a/drivers/gpu/drm/i915/gt/intel_lrc_reg.h b/drivers/gpu/drm/i915/gt/intel_lrc_reg.h index 41e5350a7a05..49d4857ad9b7 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc_reg.h +++ b/drivers/gpu/drm/i915/gt/intel_lrc_reg.h @@ -87,7 +87,6 @@ #define GEN11_CSB_WRITE_PTR_MASK (GEN11_CSB_PTR_MASK << 0) #define MAX_CONTEXT_HW_ID (1 << 21) /* exclusive */ -#define MAX_GUC_CONTEXT_HW_ID (1 << 20) /* exclusive */ #define GEN11_MAX_CONTEXT_HW_ID (1 << 11) /* exclusive */ /* in Gen12 ID 0x7FF is reserved to indicate idle */ #define GEN12_MAX_CONTEXT_HW_ID (GEN11_MAX_CONTEXT_HW_ID - 1) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 8c7b92f699f1..30773cd699f5 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -7,6 +7,7 @@ #define _INTEL_GUC_H_ #include +#include #include "intel_uncore.h" #include "intel_guc_fw.h" @@ -44,6 +45,14 @@ struct intel_guc { void (*disable)(struct intel_guc *guc); } interrupts; + /* + * contexts_lock protects the pool of free guc ids and a linked list of + * guc ids available to be stolen + */ + spinlock_t contexts_lock; + struct ida guc_ids; + struct list_head guc_id_list; + bool submission_selected;
Re: [PATCH 02/15] drm/i915/guc/slpc: Initial definitions for SLPC
On 26.07.2021 21:07, Vinay Belgaumkar wrote: > Add macros to check for SLPC support. This feature is currently supported > for Gen12+ and enabled whenever GuC submission is enabled/selected. > > Include templates for SLPC init/fini and enable. > > v2: Move SLPC helper functions to intel_guc_slpc.c/.h. Define basic > template for SLPC structure in intel_guc_slpc_types.h. Fix copyright (Michal > W) > > v3: Review comments (Michal W) > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > Signed-off-by: Daniele Ceraolo Spurio > > drm/i915/guc/slpc: Lay out slpc init/enable/fini > > Declare init/fini and enable function templates. > > v2: Rebase > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > drivers/gpu/drm/i915/Makefile | 1 + > drivers/gpu/drm/i915/gt/uc/intel_guc.c| 2 + > drivers/gpu/drm/i915/gt/uc/intel_guc.h| 4 ++ > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 45 +++ > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 33 ++ > .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 12 + > drivers/gpu/drm/i915/gt/uc/intel_uc.c | 6 ++- > drivers/gpu/drm/i915/gt/uc/intel_uc.h | 2 + > 8 files changed, 103 insertions(+), 2 deletions(-) > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile > index ab7679957623..d8eac4468df9 100644 > --- a/drivers/gpu/drm/i915/Makefile > +++ b/drivers/gpu/drm/i915/Makefile > @@ -186,6 +186,7 @@ i915-y += gt/uc/intel_uc.o \ > gt/uc/intel_guc_fw.o \ > gt/uc/intel_guc_log.o \ > gt/uc/intel_guc_log_debugfs.o \ > + gt/uc/intel_guc_slpc.o \ > gt/uc/intel_guc_submission.o \ > gt/uc/intel_huc.o \ > gt/uc/intel_huc_debugfs.o \ > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > index 979128e28372..39bc3c16057b 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > @@ -7,6 +7,7 @@ > #include "gt/intel_gt_irq.h" > #include "gt/intel_gt_pm_irq.h" > #include "intel_guc.h" > +#include "intel_guc_slpc.h" > #include "intel_guc_ads.h" > #include "intel_guc_submission.h" > #include "i915_drv.h" > @@ -157,6 +158,7 @@ void intel_guc_init_early(struct intel_guc *guc) > intel_guc_ct_init_early(&guc->ct); > intel_guc_log_init_early(&guc->log); > intel_guc_submission_init_early(guc); > + intel_guc_slpc_init_early(&guc->slpc); > > mutex_init(&guc->send_mutex); > spin_lock_init(&guc->irq_lock); > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > index a9547069ee7e..15ad2eaee473 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > @@ -15,6 +15,7 @@ > #include "intel_guc_ct.h" > #include "intel_guc_log.h" > #include "intel_guc_reg.h" > +#include "intel_guc_slpc_types.h" > #include "intel_uc_fw.h" > #include "i915_utils.h" > #include "i915_vma.h" > @@ -30,6 +31,7 @@ struct intel_guc { > struct intel_uc_fw fw; > struct intel_guc_log log; > struct intel_guc_ct ct; > + struct intel_guc_slpc slpc; > > /* Global engine used to submit requests to GuC */ > struct i915_sched_engine *sched_engine; > @@ -57,6 +59,8 @@ struct intel_guc { > > bool submission_supported; > bool submission_selected; > + bool slpc_supported; > + bool slpc_selected; (I know that you were following existing code, but we might do better and since you have to resend it anyway without patch 1/15 ...) as we have here: + struct intel_guc_slpc slpc; then maybe both supported/selected shall be moved there as: struct intel_guc_slpc { + bool supported; + bool selected; }; so the struct wont be empty any more, with that fixed: Reviewed-by: Michal Wajdeczko > > struct i915_vma *ads_vma; > struct __guc_ads_blob *ads_blob; > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > new file mode 100644 > index ..7275100ef8f8 > --- /dev/null > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -0,0 +1,45 @@ > +// SPDX-License-Ide
Re: [PATCH 04/15] drm/i915/guc/slpc: Adding SLPC communication interfaces
On 26.07.2021 21:07, Vinay Belgaumkar wrote: > Add constants and params that are needed to configure SLPC. > > v2: Add a new abi header for SLPC. Replace bitfields with > genmasks. Address other comments from Michal W. > > v3: Add slpc H2G format in abi, other review commments (Michal W) > > v4: Update status bits according to latest spec > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 1 - > .../drm/i915/gt/uc/abi/guc_actions_slpc_abi.h | 235 ++ > drivers/gpu/drm/i915/gt/uc/intel_guc.c| 3 + > drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 7 + > 4 files changed, 245 insertions(+), 1 deletion(-) > create mode 100644 drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h > > diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > index d832c8f11c11..ca538e5de940 100644 > --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > @@ -135,7 +135,6 @@ enum intel_guc_action { > INTEL_GUC_ACTION_SET_CONTEXT_PREEMPTION_TIMEOUT = 0x1007, > INTEL_GUC_ACTION_CONTEXT_RESET_NOTIFICATION = 0x1008, > INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION = 0x1009, > - INTEL_GUC_ACTION_SLPC_REQUEST = 0x3003, > INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000, > INTEL_GUC_ACTION_REGISTER_CONTEXT = 0x4502, > INTEL_GUC_ACTION_DEREGISTER_CONTEXT = 0x4503, > diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h > b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h > new file mode 100644 > index ..70b300d4a536 > --- /dev/null > +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h > @@ -0,0 +1,235 @@ > +/* SPDX-License-Identifier: MIT */ > +/* > + * Copyright © 2021 Intel Corporation > + */ > + > +#ifndef _GUC_ACTIONS_SLPC_ABI_H_ > +#define _GUC_ACTIONS_SLPC_ABI_H_ > + > +#include > + > +/** > + * DOC: SLPC SHARED DATA STRUCTURE > + * > + * > ++--+--+ > + * | CL | Bytes| Description > | > + * > ++==+==+ > + * | 1 | 0-3 | SHARED DATA SIZE > | > + * | > +--+--+ > + * || 4-7 | GLOBAL STATE > | > + * | > +--+--+ > + * || 8-11 | DISPLAY DATA ADDRESS > | > + * | > +--+--+ > + * || 12:63| PADDING > | > + * > ++--+--+ > + * || 0:63 | PADDING(PLATFORM INFO) > | > + * > ++--+--+ > + * | 3 | 0-3 | TASK STATE DATA > | > + * + > +--+--+ > + * || 4:63 | PADDING > | > + * > ++--+--+ > + * |4-21|0:1087| OVERRIDE PARAMS AND BIT FIELDS > | > + * > ++--+--+ > + * || | PADDING + EXTRA RESERVED PAGE > | > + * > ++--+--+ > + */ > + > +/* > + * SLPC exposes certain parameters for global configuration by the host. > + * These are referred to as override parameters, because in most cases > + * the host will not need to modify the default values used by SLPC. > + * SLPC remembers the default values which allows the host to easily restore > + * them by simply unsetting the override. The host can set or unset override > + * parameters during SLPC (re-)initialization using the SLPC Reset event. > + * The host can also set or unset override parameters on the fly using the > + * Parameter Set and Parameter Unset events > + */ > + > +#define SLPC_MAX_OVERRIDE_PARAMETERS 256 > +#define SLPC_OVERRIDE_BITFIELD_SIZE \ > + (SLPC_MAX_OVERRIDE_PARAMETERS / 32) > + > +#define SLPC_PAGE_SIZE_BYTES 4096 > +#define SLPC_CACHELINE_SIZE_BYTES64 > +#define SLPC_SHARED_DATA_SIZE_BYTE_HEADERSLPC_CACHELINE_SIZE_BYTES > +#define SLPC_SHARED_DATA_SIZE_BYTE_PLATFORM_INFO > SLPC_CACHELINE_SIZE_BYTES > +#define SLPC_SHARED_DATA_SIZE_BYTE_TASK_STATE > SLPC_CACHELINE_SIZE_BYTES > +#define SLPC
Re: [PATCH 05/15] drm/i915/guc/slpc: Allocate, initialize and release SLPC
On 26.07.2021 21:07, Vinay Belgaumkar wrote: > Allocate data structures for SLPC and functions for > initializing on host side. > > v2: Address review comments (Michal W) > v3: Remove unnecessary header includes (Michal W) > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > drivers/gpu/drm/i915/gt/uc/intel_guc.c| 11 ++ > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 36 ++- > .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 2 ++ > 3 files changed, 48 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > index 5b0f8c541b69..13d162353b1a 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > @@ -336,6 +336,12 @@ int intel_guc_init(struct intel_guc *guc) > goto err_ct; > } > > + if (intel_guc_slpc_is_used(guc)) { > + ret = intel_guc_slpc_init(&guc->slpc); > + if (ret) > + goto err_submission; > + } > + > /* now that everything is perma-pinned, initialize the parameters */ > guc_init_params(guc); > > @@ -346,6 +352,8 @@ int intel_guc_init(struct intel_guc *guc) > > return 0; > > +err_submission: > + intel_guc_submission_fini(guc); > err_ct: > intel_guc_ct_fini(&guc->ct); > err_ads: > @@ -368,6 +376,9 @@ void intel_guc_fini(struct intel_guc *guc) > > i915_ggtt_disable_guc(gt->ggtt); > > + if (intel_guc_slpc_is_used(guc)) > + intel_guc_slpc_fini(&guc->slpc); > + > if (intel_guc_submission_is_used(guc)) > intel_guc_submission_fini(guc); > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index 7275100ef8f8..bae4e33db0f8 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -12,6 +12,16 @@ static inline struct intel_guc *slpc_to_guc(struct > intel_guc_slpc *slpc) > return container_of(slpc, struct intel_guc, slpc); > } > > +static inline struct intel_gt *slpc_to_gt(struct intel_guc_slpc *slpc) > +{ > + return guc_to_gt(slpc_to_guc(slpc)); > +} > + > +static inline struct drm_i915_private *slpc_to_i915(struct intel_guc_slpc > *slpc) > +{ > + return slpc_to_gt(slpc)->i915; > +} > + > static bool __detect_slpc_supported(struct intel_guc *guc) > { > /* GuC SLPC is unavailable for pre-Gen12 */ > @@ -35,11 +45,35 @@ void intel_guc_slpc_init_early(struct intel_guc_slpc > *slpc) > guc->slpc_selected = __guc_slpc_selected(guc); > } > > +static int slpc_shared_data_init(struct intel_guc_slpc *slpc) > +{ > + struct intel_guc *guc = slpc_to_guc(slpc); > + struct drm_i915_private *i915 = slpc_to_i915(slpc); > + u32 size = PAGE_ALIGN(sizeof(struct slpc_shared_data)); > + int err; > + > + err = intel_guc_allocate_and_map_vma(guc, size, &slpc->vma, (void > **)&slpc->vaddr); > + if (unlikely(err)) { > + drm_err(&i915->drm, > + "Failed to allocate SLPC struct (err=%pe)\n", > + ERR_PTR(err)); > + return err; > + } > + > + return err; > +} > + > int intel_guc_slpc_init(struct intel_guc_slpc *slpc) > { > - return 0; > + GEM_BUG_ON(slpc->vma); > + > + return slpc_shared_data_init(slpc); > } > > void intel_guc_slpc_fini(struct intel_guc_slpc *slpc) > { > + if (!slpc->vma) > + return; > + > + i915_vma_unpin_and_release(&slpc->vma, I915_VMA_RELEASE_MAP); > } > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > index bfe4a7f9ce15..edcf4c05bd9f 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > @@ -7,6 +7,8 @@ > #define _INTEL_GUC_SLPC_TYPES_H_ > > struct intel_guc_slpc { > + struct i915_vma *vma; > + struct slpc_shared_data *vaddr; > }; > > #endif > Reviewed-by: Michal Wajdeczko
Re: [Intel-gfx] [PATCH 06/15] drm/i915/guc/slpc: Enable SLPC and add related H2G events
On 26.07.2021 21:07, Vinay Belgaumkar wrote: > Add methods for interacting with GuC for enabling SLPC. Enable > SLPC after GuC submission has been established. GuC load will > fail if SLPC cannot be successfully initialized. Add various > helper methods to set/unset the parameters for SLPC. They can > be set using H2G calls or directly setting bits in the shared > data structure. > > v2: Address several review comments, add new helpers for > decoding the SLPC min/max frequencies. Use masks instead of hardcoded > constants. (Michal W) > > v3: Split global_state_to_string function, and check for positive > non-zero return value from intel_guc_send() (Michal W) > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 237 ++ > .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 2 + > drivers/gpu/drm/i915/gt/uc/intel_uc.c | 8 + > 3 files changed, 247 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index bae4e33db0f8..f5808d2acbca 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -45,6 +45,40 @@ void intel_guc_slpc_init_early(struct intel_guc_slpc *slpc) > guc->slpc_selected = __guc_slpc_selected(guc); > } > > +static void slpc_mem_set_param(struct slpc_shared_data *data, > + u32 id, u32 value) > +{ > + GEM_BUG_ON(id >= SLPC_MAX_OVERRIDE_PARAMETERS); > + /* > + * When the flag bit is set, corresponding value will be read > + * and applied by slpc. s/slpc/SLPC > + */ > + data->override_params.bits[id >> 5] |= (1 << (id % 32)); > + data->override_params.values[id] = value; > +} > + > +static void slpc_mem_set_enabled(struct slpc_shared_data *data, > + u8 enable_id, u8 disable_id) > +{ > + /* > + * Enabling a param involves setting the enable_id > + * to 1 and disable_id to 0. > + */ > + slpc_mem_set_param(data, enable_id, 1); > + slpc_mem_set_param(data, disable_id, 0); > +} > + > +static void slpc_mem_set_disabled(struct slpc_shared_data *data, > + u8 enable_id, u8 disable_id) > +{ > + /* > + * Disabling a param involves setting the enable_id > + * to 0 and disable_id to 1. > + */ > + slpc_mem_set_param(data, disable_id, 1); > + slpc_mem_set_param(data, enable_id, 0); > +} > + > static int slpc_shared_data_init(struct intel_guc_slpc *slpc) > { > struct intel_guc *guc = slpc_to_guc(slpc); > @@ -63,6 +97,129 @@ static int slpc_shared_data_init(struct intel_guc_slpc > *slpc) > return err; > } > > +static u32 slpc_get_state(struct intel_guc_slpc *slpc) > +{ > + struct slpc_shared_data *data; > + > + GEM_BUG_ON(!slpc->vma); > + > + drm_clflush_virt_range(slpc->vaddr, sizeof(u32)); > + data = slpc->vaddr; > + > + return data->header.global_state; > +} > + > +static bool slpc_is_running(struct intel_guc_slpc *slpc) > +{ > + return (slpc_get_state(slpc) == SLPC_GLOBAL_STATE_RUNNING); extra ( ) not needed > +} > + > +static int guc_action_slpc_query(struct intel_guc *guc, u32 offset) > +{ > + u32 request[] = { > + INTEL_GUC_ACTION_SLPC_REQUEST, > + SLPC_EVENT(SLPC_EVENT_QUERY_TASK_STATE, 2), > + offset, > + 0, > + }; > + int ret; > + > + ret = intel_guc_send(guc, request, ARRAY_SIZE(request)); > + > + return ret > 0 ? -EPROTO : ret; > +} > + > +static int slpc_query_task_state(struct intel_guc_slpc *slpc) > +{ > + struct intel_guc *guc = slpc_to_guc(slpc); > + struct drm_i915_private *i915 = slpc_to_i915(slpc); > + u32 shared_data_gtt_offset = intel_guc_ggtt_offset(guc, slpc->vma); just "offset" ? or maybe pass directly in call below ? > + int ret; > + > + ret = guc_action_slpc_query(guc, shared_data_gtt_offset); > + if (ret) > + drm_err(&i915->drm, "Query task state data returned (%pe)\n", "Failed to query task state (%pe)\n" ? > + ERR_PTR(ret)); > + > + drm_clflush_virt_range(slpc->vaddr, SLPC_PAGE_SIZE_BYTES); > + > + return ret; > +} > + > +static const char *slpc_global_state_to_string(enum slpc_global_state state) > +{ > + const char *str = NULL; > + > + switch (state) { > + case SLPC_GLOBAL_STATE_NOT_RUNNING: > + str = "not running"; > + break; > + case SLPC_GLOBAL_STATE_INITIALIZING: > + str = "initializing"; > + break; > + case SLPC_GLOBAL_STATE_RESETTING: > + str = "resetting"; > + break; > + case SLPC_GLOBAL_STATE_RUNNING: > + str = "running"; > + break; > + case SLPC_GLOBAL_STATE_SHUTTING_DOWN: > + str = "shutting down"; > + break; > + case SLPC_GLOBA
Re: [Intel-gfx] [PATCH 08/15] drm/i915/guc/slpc: Add methods to set min/max frequency
On 26.07.2021 21:07, Vinay Belgaumkar wrote: > Add param set h2g helpers to set the min and max frequencies s/h2g/H2G > for use by SLPC. > > v2: Address review comments (Michal W) > v3: Check for positive error code (Michal W) > > Signed-off-by: Sundaresan Sujaritha > Signed-off-by: Vinay Belgaumkar > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 89 - > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 2 + > 2 files changed, 90 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index f5808d2acbca..63656640189c 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -109,6 +109,21 @@ static u32 slpc_get_state(struct intel_guc_slpc *slpc) > return data->header.global_state; > } > > +static int guc_action_slpc_set_param(struct intel_guc *guc, u8 id, u32 value) > +{ > + u32 request[] = { > + INTEL_GUC_ACTION_SLPC_REQUEST, > + SLPC_EVENT(SLPC_EVENT_PARAMETER_SET, 2), > + id, > + value, > + }; > + int ret; > + > + ret = intel_guc_send(guc, request, ARRAY_SIZE(request)); > + > + return ret > 0 ? -EPROTO : ret; > +} > + > static bool slpc_is_running(struct intel_guc_slpc *slpc) > { > return (slpc_get_state(slpc) == SLPC_GLOBAL_STATE_RUNNING); > @@ -118,7 +133,7 @@ static int guc_action_slpc_query(struct intel_guc *guc, > u32 offset) > { > u32 request[] = { > INTEL_GUC_ACTION_SLPC_REQUEST, > - SLPC_EVENT(SLPC_EVENT_QUERY_TASK_STATE, 2), > + SLPC_EVENT(SLPC_EVENT_QUERY_TASK_STATE, 2), this should be fixed in original patch > offset, > 0, > }; > @@ -146,6 +161,15 @@ static int slpc_query_task_state(struct intel_guc_slpc > *slpc) > return ret; > } > > +static int slpc_set_param(struct intel_guc_slpc *slpc, u8 id, u32 value) > +{ > + struct intel_guc *guc = slpc_to_guc(slpc); > + > + GEM_BUG_ON(id >= SLPC_MAX_PARAM); > + > + return guc_action_slpc_set_param(guc, id, value); > +} > + > static const char *slpc_global_state_to_string(enum slpc_global_state state) > { > const char *str = NULL; > @@ -251,6 +275,69 @@ static u32 slpc_decode_max_freq(struct intel_guc_slpc > *slpc) > GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER); > } > > +/** > + * intel_guc_slpc_set_max_freq() - Set max frequency limit for SLPC. > + * @slpc: pointer to intel_guc_slpc. > + * @val: frequency (MHz) > + * > + * This function will invoke GuC SLPC action to update the max frequency > + * limit for unslice. > + * > + * Return: 0 on success, non-zero error code on failure. > + */ > +int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val) > +{ > + struct drm_i915_private *i915 = slpc_to_i915(slpc); > + intel_wakeref_t wakeref; > + int ret; > + > + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { > + ret = slpc_set_param(slpc, > +SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ, > +val); > + if (ret) { > + drm_err(&i915->drm, > + "Set max frequency unslice returned (%pe)\n", > ERR_PTR(ret)); maybe generic error reporting could be moved to slpc_set_param() ? > + /* Return standardized err code for sysfs */ > + ret = -EIO; at this point we don't know if this function is for sysfs only I would sanitize error in "store" hook if really needed ssize_t slpc_max_freq_store(... const char *buf, size_t count) { ... err = intel_guc_slpc_set_max_freq(slpc, val); return err ? -EIO : count; } > + } > + } > + > + return ret; > +} > + > +/** > + * intel_guc_slpc_set_min_freq() - Set min frequency limit for SLPC. > + * @slpc: pointer to intel_guc_slpc. > + * @val: frequency (MHz) > + * > + * This function will invoke GuC SLPC action to update the min unslice > + * frequency. > + * > + * Return: 0 on success, non-zero error code on failure. > + */ > +int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val) > +{ > + int ret; > + struct intel_guc *guc = slpc_to_guc(slpc); > + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; > + intel_wakeref_t wakeref; > + > + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { > + ret = slpc_set_param(slpc, > +SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ, > +val); > + if (ret) { > + drm_err(&i915->drm, > + "Set min frequency for unslice returned > (%pe)\n", ERR_PTR(ret)); > + /* Return standardized err code for sysfs */ > + ret = -EIO; > + } > + } same here Michal > + > + return ret; >
Re: [Intel-gfx] [PATCH 09/15] drm/i915/guc/slpc: Add get max/min freq hooks
On 26.07.2021 21:07, Vinay Belgaumkar wrote: > Add helpers to read the min/max frequency being used > by SLPC. This is done by send a H2G command which forces > SLPC to update the shared data struct which can then be > read. These helpers will be used in a sysfs patch later > on. > > v2: Address review comments (Michal W) > v3: Return err in case of query failure (Michal W) > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 54 + > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 2 + > 2 files changed, 56 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index 63656640189c..c653bba3b5eb 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -306,6 +306,33 @@ int intel_guc_slpc_set_max_freq(struct intel_guc_slpc > *slpc, u32 val) > return ret; > } > > +/** > + * intel_guc_slpc_get_max_freq() - Get max frequency limit for SLPC. > + * @slpc: pointer to intel_guc_slpc. > + * @val: pointer to val which will hold max frequency (MHz) > + * > + * This function will invoke GuC SLPC action to read the max frequency > + * limit for unslice. > + * > + * Return: 0 on success, non-zero error code on failure. > + */ > +int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val) > +{ > + struct drm_i915_private *i915 = slpc_to_i915(slpc); > + intel_wakeref_t wakeref; > + int ret = 0; > + > + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { > + /* Force GuC to update task data */ > + ret = slpc_query_task_state(slpc); > + > + if (!ret) > + *val = slpc_decode_max_freq(slpc); > + } > + > + return ret; > +} > + > /** > * intel_guc_slpc_set_min_freq() - Set min frequency limit for SLPC. > * @slpc: pointer to intel_guc_slpc. > @@ -338,6 +365,33 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc > *slpc, u32 val) > return ret; > } > > +/** > + * intel_guc_slpc_get_min_freq() - Get min frequency limit for SLPC. > + * @slpc: pointer to intel_guc_slpc. > + * @val: pointer to val which will hold min frequency (MHz) > + * > + * This function will invoke GuC SLPC action to read the min frequency > + * limit for unslice. > + * > + * Return: 0 on success, non-zero error code on failure. > + */ > +int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val) > +{ > + intel_wakeref_t wakeref; > + struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915; use slpc_to_i915() and in this order: struct drm_i915_private *i915 = slpc_to_i915(slpc); intel_wakeref_t wakeref; int ret = 0; with that fixed, Reviewed-by: Michal Wajdeczko > + int ret = 0; > + > + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { > + /* Force GuC to update task data */ > + ret = slpc_query_task_state(slpc); > + > + if (!ret) > + *val = slpc_decode_min_freq(slpc); > + } > + > + return ret; > +} > + > /* > * intel_guc_slpc_enable() - Start SLPC > * @slpc: pointer to intel_guc_slpc. > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > index e594510497ec..92d7afd44f07 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > @@ -31,5 +31,7 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc); > void intel_guc_slpc_fini(struct intel_guc_slpc *slpc); > int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val); > int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val); > +int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val); > +int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val); > > #endif >
Re: [PATCH 10/15] drm/i915/guc/slpc: Add debugfs for SLPC info
On 26.07.2021 21:07, Vinay Belgaumkar wrote: > This prints out relevant SLPC info from the SLPC shared structure. > > We will send a h2g message which forces SLPC to update the s/h2g/H2G > shared data structure with latest information before reading it. > > v2: Address review comments (Michal W) > v3: Remove unnecessary tasks from slpc_info (Michal W) > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > .../gpu/drm/i915/gt/uc/intel_guc_debugfs.c| 22 ++ > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 29 +++ > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 4 ++- > 3 files changed, 54 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c > index 72ddfff42f7d..3244e54b1337 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c > @@ -12,6 +12,7 @@ > #include "gt/uc/intel_guc_ct.h" > #include "gt/uc/intel_guc_ads.h" > #include "gt/uc/intel_guc_submission.h" > +#include "gt/uc/intel_guc_slpc.h" > > static int guc_info_show(struct seq_file *m, void *data) > { > @@ -50,11 +51,32 @@ static int guc_registered_contexts_show(struct seq_file > *m, void *data) > } > DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_registered_contexts); > > +static int guc_slpc_info_show(struct seq_file *m, void *unused) > +{ > + struct intel_guc *guc = m->private; > + struct intel_guc_slpc *slpc = &guc->slpc; > + struct drm_printer p = drm_seq_file_printer(m); > + > + if (!intel_guc_slpc_is_used(guc)) > + return -ENODEV; > + > + return intel_guc_slpc_info(slpc, &p); > +} > +DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_slpc_info); > + > +static bool intel_eval_slpc_support(void *data) > +{ > + struct intel_guc *guc = (struct intel_guc *)data; > + > + return intel_guc_slpc_is_used(guc); > +} > + > void intel_guc_debugfs_register(struct intel_guc *guc, struct dentry *root) > { > static const struct debugfs_gt_file files[] = { > { "guc_info", &guc_info_fops, NULL }, > { "guc_registered_contexts", &guc_registered_contexts_fops, > NULL }, > + { "guc_slpc_info", &guc_slpc_info_fops, > &intel_eval_slpc_support}, > }; > > if (!intel_guc_is_supported(guc)) > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index c653bba3b5eb..995d3d4807a3 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -448,6 +448,35 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) > return 0; > } > > +int intel_guc_slpc_info(struct intel_guc_slpc *slpc, struct drm_printer *p) nit: intel_guc_slpc_print_info ? > +{ > + struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915; use slpc_to_i915() > + struct slpc_shared_data *data = slpc->vaddr; > + struct slpc_task_state_data *slpc_tasks; > + intel_wakeref_t wakeref; > + int ret = 0; > + > + GEM_BUG_ON(!slpc->vma); > + > + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { > + ret = slpc_query_task_state(slpc); > + > + if (!ret) { > + slpc_tasks = &data->task_state_data; > + > + drm_printf(p, "\tSLPC state: %s\n", > slpc_get_state_string(slpc)); > + drm_printf(p, "\tGTPERF task active: %s\n", > + yesno(slpc_tasks->status & > SLPC_GTPERF_TASK_ENABLED)); > + drm_printf(p, "\tMax freq: %u MHz\n", > + slpc_decode_max_freq(slpc)); > + drm_printf(p, "\tMin freq: %u MHz\n", > + slpc_decode_min_freq(slpc)); > + } > + } > + > + return ret; > +} > + > void intel_guc_slpc_fini(struct intel_guc_slpc *slpc) > { > if (!slpc->vma) > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > index 92d7afd44f07..d133c8020c16 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > @@ -9,6 +9,8 @@ > #include "intel_guc_submission.h" > #include "intel_guc_slpc_types.h" > > +struct drm_printer; > + > static inline bool intel_guc_slpc_is_supported(st
Re: [PATCH 12/15] drm/i915/guc/slpc: Cache platform frequency limits
On 26.07.2021 21:07, Vinay Belgaumkar wrote: > Cache rp0, rp1 and rpn platform limits into SLPC structure > for range checking while setting min/max frequencies. > > Also add "soft" limits which keep track of frequency changes > made from userland. These are initially set to platform min > and max. > > v2: Address review comments (Michal W) > v3: Formatting (Michal W) > > Signed-off-by: Vinay Belgaumkar > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 97 +++ > .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 11 +++ > drivers/gpu/drm/i915/i915_reg.h | 3 + > 3 files changed, 111 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index c79dba60b2e6..a98cbf274862 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -94,6 +94,9 @@ static int slpc_shared_data_init(struct intel_guc_slpc > *slpc) > return err; > } > > + slpc->max_freq_softlimit = 0; > + slpc->min_freq_softlimit = 0; > + > return err; > } > > @@ -124,6 +127,18 @@ static int guc_action_slpc_set_param(struct intel_guc > *guc, u8 id, u32 value) > return ret > 0 ? -EPROTO : ret; > } > > +static int guc_action_slpc_unset_param(struct intel_guc *guc, u8 id) > +{ > + u32 request[] = { > + INTEL_GUC_ACTION_SLPC_REQUEST, > + SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 2), > + id, > + }; > + > + return intel_guc_send(guc, request, ARRAY_SIZE(request)); > +} > + > + > static bool slpc_is_running(struct intel_guc_slpc *slpc) > { > return (slpc_get_state(slpc) == SLPC_GLOBAL_STATE_RUNNING); > @@ -170,6 +185,16 @@ static int slpc_set_param(struct intel_guc_slpc *slpc, > u8 id, u32 value) > return guc_action_slpc_set_param(guc, id, value); > } > > +static int slpc_unset_param(struct intel_guc_slpc *slpc, > + u8 id) > +{ > + struct intel_guc *guc = slpc_to_guc(slpc); > + > + GEM_BUG_ON(id >= SLPC_MAX_PARAM); > + > + return guc_action_slpc_unset_param(guc, id); > +} > + > static const char *slpc_global_state_to_string(enum slpc_global_state state) > { > const char *str = NULL; > @@ -406,6 +431,55 @@ void intel_guc_pm_intrmsk_enable(struct intel_gt *gt) > GEN6_PMINTRMSK, pm_intrmsk_mbz, 0); > } > > +static int intel_guc_slpc_set_softlimits(struct intel_guc_slpc *slpc) nit: "intel_" prefix not needed for static function > +{ > + int ret = 0; > + > + /* Softlimits are initially equivalent to platform limits > + * unless they have deviated from defaults, in which case, > + * we retain the values and set min/max accordingly. > + */ fix style for multi-line comment > + if (!slpc->max_freq_softlimit) > + slpc->max_freq_softlimit = slpc->rp0_freq; > + else if (slpc->max_freq_softlimit != slpc->rp0_freq) > + ret = intel_guc_slpc_set_max_freq(slpc, > + slpc->max_freq_softlimit); > + > + if (!slpc->min_freq_softlimit) > + slpc->min_freq_softlimit = slpc->min_freq; > + else if (slpc->min_freq_softlimit != slpc->min_freq) > + ret = intel_guc_slpc_set_min_freq(slpc, > + slpc->min_freq_softlimit); > + > + return ret; > +} > + > +static void intel_guc_slpc_ignore_eff_freq(struct intel_guc_slpc *slpc, bool > ignore) > +{ > + if (ignore) { > + /* A failure here does not affect the algorithm in a fatal way > */ is this comment just for "ignore" case or whole function ? (as you don't check for errors in "else" case anyway) > + slpc_set_param(slpc, > +SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY, > +ignore); > + slpc_set_param(slpc, > +SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ, > +slpc->min_freq); > + } else { > + slpc_unset_param(slpc, > +SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY); > + slpc_unset_param(slpc, > +SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ); > + } > +} > + > +static void intel_guc_slpc_use_fused_rp0(struct intel_guc_slpc *slpc) > +{ > + /* Force slpc to used platform rp0 */ s/slpc/SLPC > + slpc_set_param(slpc, > +SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ, > +slpc->rp0_freq); hmm, likely indent is wrong, did you run checkpatch.pl ? > +} > + > /* > * intel_guc_slpc_enable() - Start SLPC > * @slpc: pointer to intel_guc_slpc. > @@ -423,6 +497,7 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) > { > struct drm_i915_private *i915 = slpc_to_i915(slpc); > struct slpc_shared_data *data; > + u32 rp_state_cap; > int ret; > > GEM_BUG_ON(!slpc->vma); > @@ -460,6 +535,28 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slp
Re: [PATCH 13/15] drm/i915/guc/slpc: Sysfs hooks for SLPC
On 26.07.2021 21:07, Vinay Belgaumkar wrote: > Update the get/set min/max freq hooks to work for > SLPC case as well. Consolidate helpers for requested/min/max > frequency get/set to intel_rps where the proper action can > be taken depending on whether SLPC is enabled. > > v2: Add wrappers for getting rp0/1/n frequencies, update > softlimits in set min/max SLPC functions. Also check for > boundary conditions before setting them. > > v3: Address review comments (Michal W) > > Acked-by: Michal Wajdeczko > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Tvrtko Ursulin > Signed-off-by: Sujaritha Sundaresan > --- > drivers/gpu/drm/i915/gt/intel_rps.c | 165 > drivers/gpu/drm/i915/gt/intel_rps.h | 11 ++ > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 14 ++ > drivers/gpu/drm/i915/i915_pmu.c | 2 +- > drivers/gpu/drm/i915/i915_reg.h | 2 + > drivers/gpu/drm/i915/i915_sysfs.c | 77 ++--- > 6 files changed, 207 insertions(+), 64 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c > b/drivers/gpu/drm/i915/gt/intel_rps.c > index e858eeb2c59d..48d4147165a9 100644 > --- a/drivers/gpu/drm/i915/gt/intel_rps.c > +++ b/drivers/gpu/drm/i915/gt/intel_rps.c > @@ -37,6 +37,13 @@ static struct intel_uncore *rps_to_uncore(struct intel_rps > *rps) > return rps_to_gt(rps)->uncore; > } > > +static struct intel_guc_slpc *rps_to_slpc(struct intel_rps *rps) > +{ > + struct intel_gt *gt = rps_to_gt(rps); > + > + return >->uc.guc.slpc; > +} > + > static bool rps_uses_slpc(struct intel_rps *rps) > { > struct intel_gt *gt = rps_to_gt(rps); > @@ -1960,6 +1967,164 @@ u32 intel_rps_read_actual_frequency(struct intel_rps > *rps) > return freq; > } > > +u32 intel_rps_read_punit_req(struct intel_rps *rps) > +{ > + struct intel_uncore *uncore = rps_to_uncore(rps); > + > + return intel_uncore_read(uncore, GEN6_RPNSWREQ); > +} > + > +u32 intel_rps_get_req(struct intel_rps *rps, u32 pureq) hmm, "rps" looks to be not needed here btw, shouldn't this function be static ? > +{ > + u32 req = pureq >> GEN9_SW_REQ_UNSLICE_RATIO_SHIFT; > + > + return req; > +} > + > +u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps) > +{ > + u32 freq = intel_rps_get_req(rps, intel_rps_read_punit_req(rps)); > + > + return intel_gpu_freq(rps, freq); > +} > + > +u32 intel_rps_get_requested_frequency(struct intel_rps *rps) > +{ > + if (rps_uses_slpc(rps)) > + return intel_rps_read_punit_req_frequency(rps); > + else > + return intel_gpu_freq(rps, rps->cur_freq); > +} > + > +u32 intel_rps_get_max_frequency(struct intel_rps *rps) > +{ > + struct intel_guc_slpc *slpc = rps_to_slpc(rps); > + > + if (rps_uses_slpc(rps)) > + return slpc->max_freq_softlimit; > + else > + return intel_gpu_freq(rps, rps->max_freq_softlimit); > +} > + > +u32 intel_rps_get_rp0_frequency(struct intel_rps *rps) > +{ > + struct intel_guc_slpc *slpc = rps_to_slpc(rps); > + > + if (rps_uses_slpc(rps)) > + return slpc->rp0_freq; > + else > + return intel_gpu_freq(rps, rps->rp0_freq); > +} > + > +u32 intel_rps_get_rp1_frequency(struct intel_rps *rps) > +{ > + struct intel_guc_slpc *slpc = rps_to_slpc(rps); > + > + if (rps_uses_slpc(rps)) > + return slpc->rp1_freq; > + else > + return intel_gpu_freq(rps, rps->rp1_freq); > +} > + > +u32 intel_rps_get_rpn_frequency(struct intel_rps *rps) > +{ > + struct intel_guc_slpc *slpc = rps_to_slpc(rps); > + > + if (rps_uses_slpc(rps)) > + return slpc->min_freq; > + else > + return intel_gpu_freq(rps, rps->min_freq); > +} > + > +int intel_rps_set_max_frequency(struct intel_rps *rps, u32 val) > +{ > + struct drm_i915_private *i915 = rps_to_i915(rps); > + struct intel_guc_slpc *slpc = rps_to_slpc(rps); > + int ret = 0; > + > + if (rps_uses_slpc(rps)) > + return intel_guc_slpc_set_max_freq(slpc, val); few above functions are implemented as nice dispatcher if (rps_uses_slpc(rps)) return ... slpc stuff; else return ... gpu stuff; can we have something similar here ? likely just putting below code into helper will do the trick > + > + mutex_lock(&rps->lock); > + > + val = intel_freq_opcode(rps, val); > + if (val < rps->min_freq || > + val > rps->m
Re: [Intel-gfx] [PATCH 06/15] drm/i915/guc/slpc: Enable SLPC and add related H2G events
On 27.07.2021 22:00, Belgaumkar, Vinay wrote: > > > On 7/27/2021 8:12 AM, Michal Wajdeczko wrote: >> >> >> On 26.07.2021 21:07, Vinay Belgaumkar wrote: >>> Add methods for interacting with GuC for enabling SLPC. Enable >>> SLPC after GuC submission has been established. GuC load will >>> fail if SLPC cannot be successfully initialized. Add various >>> helper methods to set/unset the parameters for SLPC. They can >>> be set using H2G calls or directly setting bits in the shared >>> data structure. >>> >>> v2: Address several review comments, add new helpers for >>> decoding the SLPC min/max frequencies. Use masks instead of hardcoded >>> constants. (Michal W) >>> >>> v3: Split global_state_to_string function, and check for positive >>> non-zero return value from intel_guc_send() (Michal W) >>> >>> Signed-off-by: Vinay Belgaumkar >>> Signed-off-by: Sundaresan Sujaritha >>> --- >>> drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 237 ++ >>> .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 2 + >>> drivers/gpu/drm/i915/gt/uc/intel_uc.c | 8 + >>> 3 files changed, 247 insertions(+) >>> >>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c >>> b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c >>> index bae4e33db0f8..f5808d2acbca 100644 >>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c >>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c >>> @@ -45,6 +45,40 @@ void intel_guc_slpc_init_early(struct >>> intel_guc_slpc *slpc) >>> guc->slpc_selected = __guc_slpc_selected(guc); >>> } >>> +static void slpc_mem_set_param(struct slpc_shared_data *data, >>> + u32 id, u32 value) >>> +{ >>> + GEM_BUG_ON(id >= SLPC_MAX_OVERRIDE_PARAMETERS); >>> + /* >>> + * When the flag bit is set, corresponding value will be read >>> + * and applied by slpc. >> >> s/slpc/SLPC > ok. > >> >>> + */ >>> + data->override_params.bits[id >> 5] |= (1 << (id % 32)); >>> + data->override_params.values[id] = value; >>> +} >>> + >>> +static void slpc_mem_set_enabled(struct slpc_shared_data *data, >>> + u8 enable_id, u8 disable_id) >>> +{ >>> + /* >>> + * Enabling a param involves setting the enable_id >>> + * to 1 and disable_id to 0. >>> + */ >>> + slpc_mem_set_param(data, enable_id, 1); >>> + slpc_mem_set_param(data, disable_id, 0); >>> +} >>> + >>> +static void slpc_mem_set_disabled(struct slpc_shared_data *data, >>> + u8 enable_id, u8 disable_id) >>> +{ >>> + /* >>> + * Disabling a param involves setting the enable_id >>> + * to 0 and disable_id to 1. >>> + */ >>> + slpc_mem_set_param(data, disable_id, 1); >>> + slpc_mem_set_param(data, enable_id, 0); >>> +} >>> + >>> static int slpc_shared_data_init(struct intel_guc_slpc *slpc) >>> { >>> struct intel_guc *guc = slpc_to_guc(slpc); >>> @@ -63,6 +97,129 @@ static int slpc_shared_data_init(struct >>> intel_guc_slpc *slpc) >>> return err; >>> } >>> +static u32 slpc_get_state(struct intel_guc_slpc *slpc) >>> +{ >>> + struct slpc_shared_data *data; >>> + >>> + GEM_BUG_ON(!slpc->vma); >>> + >>> + drm_clflush_virt_range(slpc->vaddr, sizeof(u32)); >>> + data = slpc->vaddr; >>> + >>> + return data->header.global_state; >>> +} >>> + >>> +static bool slpc_is_running(struct intel_guc_slpc *slpc) >>> +{ >>> + return (slpc_get_state(slpc) == SLPC_GLOBAL_STATE_RUNNING); >> >> extra ( ) not needed > > ok. > >> >>> +} >>> + >>> +static int guc_action_slpc_query(struct intel_guc *guc, u32 offset) >>> +{ >>> + u32 request[] = { >>> + INTEL_GUC_ACTION_SLPC_REQUEST, >>> + SLPC_EVENT(SLPC_EVENT_QUERY_TASK_STATE, 2), >>> + offset, >>> + 0, >>> + }; >>> + int ret; >>> + >>> + ret = intel_guc_send(guc, request, ARRAY_SIZE(request)); >>> + >>> + return ret > 0 ? -EPROTO : ret; >>> +} >>> + >>> +static int slpc_query_task_state(st
Re: [PATCH 01/14] drm/i915/guc/slpc: Initial definitions for SLPC
On 28.07.2021 23:11, Vinay Belgaumkar wrote: > Add macros to check for SLPC support. This feature is currently supported > for Gen12+ and enabled whenever GuC submission is enabled/selected. > > Include templates for SLPC init/fini and enable. > > v2: Move SLPC helper functions to intel_guc_slpc.c/.h. Define basic > template for SLPC structure in intel_guc_slpc_types.h. Fix copyright (Michal > W) > > v3: Review comments (Michal W) > > v4: Include supported/selected inside slpc struct (Michal W) > > Reviewed-by: Michal Wajdeczko > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > Signed-off-by: Daniele Ceraolo Spurio > > drm/i915/guc/slpc: Lay out slpc init/enable/fini > > Declare init/fini and enable function templates. > > v2: Rebase > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > drivers/gpu/drm/i915/Makefile | 1 + > drivers/gpu/drm/i915/gt/uc/intel_guc.c| 2 + > drivers/gpu/drm/i915/gt/uc/intel_guc.h| 2 + > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 45 +++ > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 33 ++ > .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 16 +++ > drivers/gpu/drm/i915/gt/uc/intel_uc.c | 6 ++- > drivers/gpu/drm/i915/gt/uc/intel_uc.h | 2 + > 8 files changed, 105 insertions(+), 2 deletions(-) > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile > index ab7679957623..d8eac4468df9 100644 > --- a/drivers/gpu/drm/i915/Makefile > +++ b/drivers/gpu/drm/i915/Makefile > @@ -186,6 +186,7 @@ i915-y += gt/uc/intel_uc.o \ > gt/uc/intel_guc_fw.o \ > gt/uc/intel_guc_log.o \ > gt/uc/intel_guc_log_debugfs.o \ > + gt/uc/intel_guc_slpc.o \ > gt/uc/intel_guc_submission.o \ > gt/uc/intel_huc.o \ > gt/uc/intel_huc_debugfs.o \ > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > index 979128e28372..39bc3c16057b 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > @@ -7,6 +7,7 @@ > #include "gt/intel_gt_irq.h" > #include "gt/intel_gt_pm_irq.h" > #include "intel_guc.h" > +#include "intel_guc_slpc.h" > #include "intel_guc_ads.h" > #include "intel_guc_submission.h" > #include "i915_drv.h" > @@ -157,6 +158,7 @@ void intel_guc_init_early(struct intel_guc *guc) > intel_guc_ct_init_early(&guc->ct); > intel_guc_log_init_early(&guc->log); > intel_guc_submission_init_early(guc); > + intel_guc_slpc_init_early(&guc->slpc); > > mutex_init(&guc->send_mutex); > spin_lock_init(&guc->irq_lock); > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > index a9547069ee7e..7da11a0b6059 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > @@ -15,6 +15,7 @@ > #include "intel_guc_ct.h" > #include "intel_guc_log.h" > #include "intel_guc_reg.h" > +#include "intel_guc_slpc_types.h" > #include "intel_uc_fw.h" > #include "i915_utils.h" > #include "i915_vma.h" > @@ -30,6 +31,7 @@ struct intel_guc { > struct intel_uc_fw fw; > struct intel_guc_log log; > struct intel_guc_ct ct; > + struct intel_guc_slpc slpc; > > /* Global engine used to submit requests to GuC */ > struct i915_sched_engine *sched_engine; > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > new file mode 100644 > index ..40950f1bf05c > --- /dev/null > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -0,0 +1,45 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright © 2021 Intel Corporation > + */ > + > +#include "i915_drv.h" > +#include "intel_guc_slpc.h" > +#include "gt/intel_gt.h" > + > +static inline struct intel_guc *slpc_to_guc(struct intel_guc_slpc *slpc) > +{ > + return container_of(slpc, struct intel_guc, slpc); > +} > + > +static bool __detect_slpc_supported(struct intel_guc *guc) > +{ > + /* GuC SLPC is unavailable for pre-Gen12 */ > + return guc->submission_supported && >
Re: [PATCH 03/14] drm/i915/guc/slpc: Adding SLPC communication interfaces
100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h > @@ -12,6 +12,7 @@ > #include "gt/intel_engine_types.h" > > #include "abi/guc_actions_abi.h" > +#include "abi/guc_actions_slpc_abi.h" > #include "abi/guc_errors_abi.h" > #include "abi/guc_communication_mmio_abi.h" > #include "abi/guc_communication_ctb_abi.h" > @@ -95,6 +96,7 @@ > #define GUC_CTL_WA 1 > #define GUC_CTL_FEATURE 2 > #define GUC_CTL_DISABLE_SCHEDULER (1 << 14) > +#define GUC_CTL_ENABLE_SLPCBIT(2) > > #define GUC_CTL_DEBUG3 > #define GUC_LOG_VERBOSITY_SHIFT0 > @@ -141,6 +143,11 @@ > #define GUC_ID_TO_ENGINE_INSTANCE(guc_id) \ > (((guc_id) & GUC_ENGINE_INSTANCE_MASK) >> GUC_ENGINE_INSTANCE_SHIFT) > > +#define SLPC_EVENT(id,c) (\ > +FIELD_PREP(HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ID, id) | \ > +FIELD_PREP(HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ARGC, c ) \ > +) not sure if this is right style for multi-line macro (no leading \t) but other LGTM, Reviewed-by: Michal Wajdeczko > + > static inline u8 engine_class_to_guc_class(u8 class) > { > BUILD_BUG_ON(GUC_RENDER_CLASS != RENDER_CLASS); >
Re: [PATCH 05/14] drm/i915/guc/slpc: Enable SLPC and add related H2G events
+ ERR_PTR(ret)); > + return ret; > + } > + > + ret = slpc_query_task_state(slpc); > + if (unlikely(ret < 0)) > + return ret; > + > + return 0; > +} > + > void intel_guc_slpc_fini(struct intel_guc_slpc *slpc) > { > if (!slpc->vma) > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > index 8bd753167234..3cefe19b17b2 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > @@ -8,6 +8,8 @@ > > #include > > +#define SLPC_RESET_TIMEOUT_MS 5 > + > struct intel_guc_slpc { > struct i915_vma *vma; > struct slpc_shared_data *vaddr; > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c > b/drivers/gpu/drm/i915/gt/uc/intel_uc.c > index e6bd9406c7b2..3e0cd1f05e3b 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c > @@ -500,12 +500,21 @@ static int __uc_init_hw(struct intel_uc *uc) > if (intel_uc_uses_guc_submission(uc)) > intel_guc_submission_enable(guc); > > + if (intel_uc_uses_guc_slpc(uc)) { > + ret = intel_guc_slpc_enable(&guc->slpc); > + if (ret) > + goto err_submission; > + } > + > drm_info(&i915->drm, "%s firmware %s version %u.%u %s:%s\n", >intel_uc_fw_type_repr(INTEL_UC_FW_TYPE_GUC), guc->fw.path, >guc->fw.major_ver_found, guc->fw.minor_ver_found, >"submission", >enableddisabled(intel_uc_uses_guc_submission(uc))); > > + drm_info(&i915->drm, "GuC SLPC: %s\n", > + enableddisabled(intel_uc_uses_guc_slpc(uc))); > + > if (intel_uc_uses_huc(uc)) { > drm_info(&i915->drm, "%s firmware %s version %u.%u %s:%s\n", >intel_uc_fw_type_repr(INTEL_UC_FW_TYPE_HUC), > @@ -520,6 +529,8 @@ static int __uc_init_hw(struct intel_uc *uc) > /* >* We've failed to load the firmware :( >*/ > +err_submission: > + intel_guc_submission_disable(guc); > err_log_capture: > __uc_capture_load_err_log(uc); > err_out: > make sure checkpatch.pl is happy with indents, with that Reviewed-by: Michal Wajdeczko
Re: [Intel-gfx] [PATCH 11/14] drm/i915/guc/slpc: Cache platform frequency limits
On 28.07.2021 23:11, Vinay Belgaumkar wrote: > Cache rp0, rp1 and rpn platform limits into SLPC structure > for range checking while setting min/max frequencies. > > Also add "soft" limits which keep track of frequency changes > made from userland. These are initially set to platform min > and max. > > v2: Address review comments (Michal W) > v3: Formatting (Michal W) > v4: Add separate function to parse rp values (Michal W) > v5: Perform range checking for set min/max (Michal W) > > Signed-off-by: Vinay Belgaumkar > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 115 ++ > .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 9 ++ > drivers/gpu/drm/i915/i915_reg.h | 3 + > 3 files changed, 127 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index 742918875593..bfd5fb0751fd 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -94,6 +94,9 @@ static int slpc_shared_data_init(struct intel_guc_slpc > *slpc) > return err; > } > > + slpc->max_freq_softlimit = 0; > + slpc->min_freq_softlimit = 0; shouldn't this be in intel_guc_slpc_init() ? > + > return err; > } > > @@ -124,6 +127,18 @@ static int guc_action_slpc_set_param(struct intel_guc > *guc, u8 id, u32 value) > return ret > 0 ? -EPROTO : ret; > } > > +static int guc_action_slpc_unset_param(struct intel_guc *guc, u8 id) > +{ > + u32 request[] = { > + GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST, > + SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 2), > + id, > + }; > + > + return intel_guc_send(guc, request, ARRAY_SIZE(request)); > +} > + > + > static bool slpc_is_running(struct intel_guc_slpc *slpc) > { > return slpc_get_state(slpc) == SLPC_GLOBAL_STATE_RUNNING; > @@ -177,6 +192,16 @@ static int slpc_set_param(struct intel_guc_slpc *slpc, > u8 id, u32 value) > return ret; > } > > +static int slpc_unset_param(struct intel_guc_slpc *slpc, > + u8 id) > +{ > + struct intel_guc *guc = slpc_to_guc(slpc); > + > + GEM_BUG_ON(id >= SLPC_MAX_PARAM); > + > + return guc_action_slpc_unset_param(guc, id); > +} > + > static const char *slpc_global_state_to_string(enum slpc_global_state state) > { > switch (state) { > @@ -307,6 +332,11 @@ int intel_guc_slpc_set_max_freq(struct intel_guc_slpc > *slpc, u32 val) > intel_wakeref_t wakeref; > int ret; > > + if ((val < slpc->min_freq) || > + (val > slpc->rp0_freq) || > + (val < slpc->min_freq_softlimit)) > + return -EINVAL; > + > with_intel_runtime_pm(&i915->runtime_pm, wakeref) { > ret = slpc_set_param(slpc, > SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ, > @@ -317,6 +347,8 @@ int intel_guc_slpc_set_max_freq(struct intel_guc_slpc > *slpc, u32 val) > ret = -EIO; > } > > + slpc->max_freq_softlimit = val; > + > return ret; > } > > @@ -363,6 +395,11 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc > *slpc, u32 val) > intel_wakeref_t wakeref; > int ret; > > + if ((val < slpc->min_freq) || > + (val > slpc->rp0_freq) || > + (val > slpc->max_freq_softlimit)) > + return -EINVAL; > + > with_intel_runtime_pm(&i915->runtime_pm, wakeref) { > ret = slpc_set_param(slpc, > SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ, > @@ -373,6 +410,8 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc > *slpc, u32 val) > ret = -EIO; > } > > + slpc->min_freq_softlimit = val; > + > return ret; > } > > @@ -418,6 +457,71 @@ void intel_guc_pm_intrmsk_enable(struct intel_gt *gt) > GEN6_PMINTRMSK, pm_intrmsk_mbz, 0); > } > > +static int slpc_set_softlimits(struct intel_guc_slpc *slpc) > +{ > + int ret = 0; > + > + /* > + * Softlimits are initially equivalent to platform limits > + * unless they have deviated from defaults, in which case, > + * we retain the values and set min/max accordingly. > + */ > + if (!slpc->max_freq_softlimit) > + slpc->max_freq_softlimit = slpc->rp0_freq; > + else if (slpc->max_freq_softlimit != slpc->rp0_freq) > + ret = intel_guc_slpc_set_max_freq(slpc, > + slpc->max_freq_softlimit); if this fails, shouldn't we reset max_freq_softlimit to platform limit ? otherwise we could be with some potentially bad value forever > + > + if (!slpc->min_freq_softlimit) > + slpc->min_freq_softlimit = slpc->min_freq; > + else if (slpc->min_freq_softlimit != slpc->min_freq) > + ret = intel_guc_slpc_set_min_freq(slpc, > + slpc->min_freq_softlimit); similar h
Re: [Intel-gfx] [PATCH 07/14] drm/i915/guc/slpc: Add methods to set min/max frequency
On 28.07.2021 23:11, Vinay Belgaumkar wrote: > Add param set h2g helpers to set the min and max frequencies > for use by SLPC. > > v2: Address review comments (Michal W) > v3: Check for positive error code (Michal W) > v4: Print generic error in set_param (Michal W) > > Signed-off-by: Sundaresan Sujaritha > Signed-off-by: Vinay Belgaumkar > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 89 + > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 2 + > 2 files changed, 91 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index da3e1f8844a9..0959cc9e104a 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -109,6 +109,21 @@ static u32 slpc_get_state(struct intel_guc_slpc *slpc) > return data->header.global_state; > } > > +static int guc_action_slpc_set_param(struct intel_guc *guc, u8 id, u32 value) > +{ > + u32 request[] = { > + GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST, > + SLPC_EVENT(SLPC_EVENT_PARAMETER_SET, 2), > + id, > + value, > + }; > + int ret; > + > + ret = intel_guc_send(guc, request, ARRAY_SIZE(request)); > + > + return ret > 0 ? -EPROTO : ret; > +} > + > static bool slpc_is_running(struct intel_guc_slpc *slpc) > { > return slpc_get_state(slpc) == SLPC_GLOBAL_STATE_RUNNING; > @@ -146,6 +161,22 @@ static int slpc_query_task_state(struct intel_guc_slpc > *slpc) > return ret; > } > > +static int slpc_set_param(struct intel_guc_slpc *slpc, u8 id, u32 value) > +{ > + struct intel_guc *guc = slpc_to_guc(slpc); > + struct drm_i915_private *i915 = slpc_to_i915(slpc); > + int ret; > + > + GEM_BUG_ON(id >= SLPC_MAX_PARAM); > + > + ret = guc_action_slpc_set_param(guc, id, value); > + if (ret) > + drm_err(&i915->drm, "Failed to set param %d to %u (%pe)\n", > + id, value, ERR_PTR(ret)); > + > + return ret; > +} > + > static const char *slpc_global_state_to_string(enum slpc_global_state state) > { > switch (state) { > @@ -260,6 +291,64 @@ static void slpc_shared_data_reset(struct > slpc_shared_data *data) > SLPC_PARAM_TASK_DISABLE_DCC); > } > > +/** > + * intel_guc_slpc_set_max_freq() - Set max frequency limit for SLPC. > + * @slpc: pointer to intel_guc_slpc. > + * @val: frequency (MHz) > + * > + * This function will invoke GuC SLPC action to update the max frequency > + * limit for unslice. > + * > + * Return: 0 on success, non-zero error code on failure. > + */ > +int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val) > +{ > + struct drm_i915_private *i915 = slpc_to_i915(slpc); > + intel_wakeref_t wakeref; > + int ret; > + > + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { > + ret = slpc_set_param(slpc, > +SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ, > +val); > + > + /* Return standardized err code for sysfs calls */ > + if (ret) > + ret = -EIO; > + } > + > + return ret; > +} > + > +/** > + * intel_guc_slpc_set_min_freq() - Set min frequency limit for SLPC. > + * @slpc: pointer to intel_guc_slpc. > + * @val: frequency (MHz) > + * > + * This function will invoke GuC SLPC action to update the min unslice > + * frequency. > + * > + * Return: 0 on success, non-zero error code on failure. > + */ > +int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val) > +{ > + struct drm_i915_private *i915 = slpc_to_i915(slpc); > + intel_wakeref_t wakeref; > + int ret; > + > + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { > + ret = slpc_set_param(slpc, > +SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ, > +val); > + > + /* Return standardized err code for sysfs calls */ > + if (ret) > + ret = -EIO; > + } > + > + return ret; > +} > + > /* > * intel_guc_slpc_enable() - Start SLPC > * @slpc: pointer to intel_guc_slpc. > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > index bc139682ad0f..788d87ff7b58 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > @@ -29,5 +29,7 @@ void intel_guc_slpc_init_early(struct intel_guc_slpc *slpc); > int intel_guc_slpc_init(struct intel_guc_slpc *slpc); > int intel_guc_slpc_enable(struct intel_guc_slpc *slpc); > void intel_guc_slpc_fini(struct intel_guc_slpc *slpc); > +int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val); > +int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val); > > #endif > Reviewed-by: Michal Wajdeczko
Re: [PATCH 12/14] drm/i915/guc/slpc: Sysfs hooks for SLPC
On 28.07.2021 23:11, Vinay Belgaumkar wrote: > Update the get/set min/max freq hooks to work for > SLPC case as well. Consolidate helpers for requested/min/max > frequency get/set to intel_rps where the proper action can > be taken depending on whether SLPC is enabled. > > v2: Add wrappers for getting rp0/1/n frequencies, update > softlimits in set min/max SLPC functions. Also check for > boundary conditions before setting them. > > v3: Address review comments (Michal W) > > v4: Add helper for host part of intel_rps_set_freq helpers (Michal W) > > Acked-by: Michal Wajdeczko > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Tvrtko Ursulin > Signed-off-by: Sujaritha Sundaresan Reviewed-by: Michal Wajdeczko > --- > drivers/gpu/drm/i915/gt/intel_rps.c | 177 > drivers/gpu/drm/i915/gt/intel_rps.h | 10 ++ > drivers/gpu/drm/i915/i915_pmu.c | 2 +- > drivers/gpu/drm/i915/i915_reg.h | 2 + > drivers/gpu/drm/i915/i915_sysfs.c | 83 +++-- > 5 files changed, 207 insertions(+), 67 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c > b/drivers/gpu/drm/i915/gt/intel_rps.c > index e858eeb2c59d..49db8ed9f80d 100644 > --- a/drivers/gpu/drm/i915/gt/intel_rps.c > +++ b/drivers/gpu/drm/i915/gt/intel_rps.c > @@ -37,6 +37,13 @@ static struct intel_uncore *rps_to_uncore(struct intel_rps > *rps) > return rps_to_gt(rps)->uncore; > } > > +static struct intel_guc_slpc *rps_to_slpc(struct intel_rps *rps) > +{ > + struct intel_gt *gt = rps_to_gt(rps); > + > + return >->uc.guc.slpc; > +} > + > static bool rps_uses_slpc(struct intel_rps *rps) > { > struct intel_gt *gt = rps_to_gt(rps); > @@ -1960,6 +1967,176 @@ u32 intel_rps_read_actual_frequency(struct intel_rps > *rps) > return freq; > } > > +u32 intel_rps_read_punit_req(struct intel_rps *rps) > +{ > + struct intel_uncore *uncore = rps_to_uncore(rps); > + > + return intel_uncore_read(uncore, GEN6_RPNSWREQ); > +} > + > +static u32 intel_rps_get_req(u32 pureq) > +{ > + u32 req = pureq >> GEN9_SW_REQ_UNSLICE_RATIO_SHIFT; > + > + return req; > +} > + > +u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps) > +{ > + u32 freq = intel_rps_get_req(intel_rps_read_punit_req(rps)); > + > + return intel_gpu_freq(rps, freq); > +} > + > +u32 intel_rps_get_requested_frequency(struct intel_rps *rps) > +{ > + if (rps_uses_slpc(rps)) > + return intel_rps_read_punit_req_frequency(rps); > + else > + return intel_gpu_freq(rps, rps->cur_freq); > +} > + > +u32 intel_rps_get_max_frequency(struct intel_rps *rps) > +{ > + struct intel_guc_slpc *slpc = rps_to_slpc(rps); > + > + if (rps_uses_slpc(rps)) > + return slpc->max_freq_softlimit; > + else > + return intel_gpu_freq(rps, rps->max_freq_softlimit); > +} > + > +u32 intel_rps_get_rp0_frequency(struct intel_rps *rps) > +{ > + struct intel_guc_slpc *slpc = rps_to_slpc(rps); > + > + if (rps_uses_slpc(rps)) > + return slpc->rp0_freq; > + else > + return intel_gpu_freq(rps, rps->rp0_freq); > +} > + > +u32 intel_rps_get_rp1_frequency(struct intel_rps *rps) > +{ > + struct intel_guc_slpc *slpc = rps_to_slpc(rps); > + > + if (rps_uses_slpc(rps)) > + return slpc->rp1_freq; > + else > + return intel_gpu_freq(rps, rps->rp1_freq); > +} > + > +u32 intel_rps_get_rpn_frequency(struct intel_rps *rps) > +{ > + struct intel_guc_slpc *slpc = rps_to_slpc(rps); > + > + if (rps_uses_slpc(rps)) > + return slpc->min_freq; > + else > + return intel_gpu_freq(rps, rps->min_freq); > +} > + > +static int set_max_freq(struct intel_rps *rps, u32 val) > +{ > + struct drm_i915_private *i915 = rps_to_i915(rps); > + int ret = 0; > + > + mutex_lock(&rps->lock); > + > + val = intel_freq_opcode(rps, val); > + if (val < rps->min_freq || > + val > rps->max_freq || > + val < rps->min_freq_softlimit) { > + ret = -EINVAL; > + goto unlock; > + } > + > + if (val > rps->rp0_freq) > + drm_dbg(&i915->drm, "User requested overclocking to %d\n", > + intel_gpu_freq(rps, val)); > + > + rps->max_freq_softlimit = val; > + > + val = clamp_t(int, rps->cur_freq, > + rps->min_freq_softlimit, > + rps->max_freq_softlimit); >
Re: [Intel-gfx] [PATCH 11/14] drm/i915/guc/slpc: Cache platform frequency limits
else if (slpc->max_freq_softlimit != slpc->rp0_freq) > + ret = intel_guc_slpc_set_max_freq(slpc, > + slpc->max_freq_softlimit); hmm, still looks more complicated than it could be ... since we're updating slpc->max_freq_softlimit in intel_guc_slpc_set_max_freq() and use of rp0_freq shouldn't fail, then maybe we can just code this as: ret = intel_guc_slpc_set_max_freq(slpc, slpc->max_freq_softlimit ?: slpc->rp0_freq); > + > + if (unlikely(ret)) > + return ret; > + > + if (!slpc->min_freq_softlimit) > + slpc->min_freq_softlimit = slpc->min_freq; > + else if (slpc->min_freq_softlimit != slpc->min_freq) > + return intel_guc_slpc_set_min_freq(slpc, > +slpc->min_freq_softlimit); and similarly here: ret = intel_guc_slpc_set_min_freq(slpc, slpc->min_freq_softlimit ?: slpc->min_freq); if (unlikely(ret)) return ret; > + > + return 0; > +} > + > +static int slpc_ignore_eff_freq(struct intel_guc_slpc *slpc, bool ignore) > +{ > + int ret = 0; > + > + if (ignore) { > + ret = slpc_set_param(slpc, > + SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY, > + ignore); > + if (!ret) > + return slpc_set_param(slpc, > + > SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ, > + slpc->min_freq); > + } else { > + ret = slpc_unset_param(slpc, > +SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY); > + if (!ret) > + return slpc_unset_param(slpc, > + > SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ); > + } > + > + return ret; > +} > + > +static int slpc_use_fused_rp0(struct intel_guc_slpc *slpc) > +{ > + /* Force SLPC to used platform rp0 */ > + return slpc_set_param(slpc, > + SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ, > + slpc->rp0_freq); > +} > + > +static void slpc_get_rp_values(struct intel_guc_slpc *slpc) > +{ > + u32 rp_state_cap; > + > + rp_state_cap = intel_uncore_read(slpc_to_gt(slpc)->uncore, > + GEN6_RP_STATE_CAP); > + > + slpc->rp0_freq = REG_FIELD_GET(RP0_CAP_MASK, rp_state_cap) * > + GT_FREQUENCY_MULTIPLIER; > + slpc->rp1_freq = REG_FIELD_GET(RP1_CAP_MASK, rp_state_cap) * > + GT_FREQUENCY_MULTIPLIER; > + slpc->min_freq = REG_FIELD_GET(RPN_CAP_MASK, rp_state_cap) * > + GT_FREQUENCY_MULTIPLIER; > +} > + > /* > * intel_guc_slpc_enable() - Start SLPC > * @slpc: pointer to intel_guc_slpc. > @@ -446,6 +559,32 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) > > intel_guc_pm_intrmsk_enable(&i915->gt); > > + slpc_get_rp_values(slpc); > + > + /* Ignore efficient freq and set min to platform min */ > + ret = slpc_ignore_eff_freq(slpc, true); > + if (unlikely(ret)) { > + drm_err(&i915->drm, "Failed to set SLPC min to RPn (%pe)\n", > + ERR_PTR(ret)); I know it's late comment, but likely this should be i915_probe_error() (if we don't have any injected errors yet, we should add some) with/without these nits (they can be done later), Reviewed-by: Michal Wajdeczko > + return ret; > + } > + > + /* Set SLPC max limit to RP0 */ > + ret = slpc_use_fused_rp0(slpc); > + if (unlikely(ret)) { > + drm_err(&i915->drm, "Failed to set SLPC max to RP0 (%pe)\n", > + ERR_PTR(ret)); > + return ret; > + } > + > + /* Revert SLPC min/max to softlimits if necessary */ > + ret = slpc_set_softlimits(slpc); > + if (unlikely(ret)) { > + drm_err(&i915->drm, "Failed to set SLPC softlimits (%pe)\n", > + ERR_PTR(ret)); > + return ret; > + } > + > return 0; > } > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > index 3cefe19b17b2..41d13527666f 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h > @@ -15,6 +15,15 @@ struct intel_guc_slpc { >
Re: [PATCH 22/22] drm/i915/guc: Add GuC kernel doc
On 17.08.2021 19:20, Daniel Vetter wrote: > On Tue, Aug 17, 2021 at 09:36:49AM -0700, Matthew Brost wrote: >> On Tue, Aug 17, 2021 at 01:11:41PM +0200, Daniel Vetter wrote: >>> On Mon, Aug 16, 2021 at 06:51:39AM -0700, Matthew Brost wrote: Add GuC kernel doc for all structures added thus far for GuC submission and update the main GuC submission section with the new interface details. Signed-off-by: Matthew Brost >>> >>> There's quite a bit more, e.g. intel_guc_ct, which has it's own world of >>> locking design that also doesn't feel too consistent. >>> >> >> That is a different layer than GuC submission so I don't we should >> mention anything about that layer here. Didn't really write that layer >> and it super painful to touch that code so I'm going to stay out of any >> rework you think we need to do there. > > Well there's three locks It's likely me. There is one lock for the recv CTB, one for the send CTB, one for the list of read messages ready to post process - do you want to use single lock for both CTBs or single lock for all cases in CT ? Michal disclaimer: outstanding_g2h are not part of the CTB layer > there plus it leaks out (you have your > outstanding_submission_g2h atomic_t which is very closed tied to well, > outstanding guc transmissions), so I guess I need someone else for that? >
Re: [PATCH 22/22] drm/i915/guc: Add GuC kernel doc
On 17.08.2021 19:34, Daniel Vetter wrote: > On Tue, Aug 17, 2021 at 07:27:18PM +0200, Michal Wajdeczko wrote: >> >> >> On 17.08.2021 19:20, Daniel Vetter wrote: >>> On Tue, Aug 17, 2021 at 09:36:49AM -0700, Matthew Brost wrote: >>>> On Tue, Aug 17, 2021 at 01:11:41PM +0200, Daniel Vetter wrote: >>>>> On Mon, Aug 16, 2021 at 06:51:39AM -0700, Matthew Brost wrote: >>>>>> Add GuC kernel doc for all structures added thus far for GuC submission >>>>>> and update the main GuC submission section with the new interface >>>>>> details. >>>>>> >>>>>> Signed-off-by: Matthew Brost >>>>> >>>>> There's quite a bit more, e.g. intel_guc_ct, which has it's own world of >>>>> locking design that also doesn't feel too consistent. >>>>> >>>> >>>> That is a different layer than GuC submission so I don't we should >>>> mention anything about that layer here. Didn't really write that layer >>>> and it super painful to touch that code so I'm going to stay out of any >>>> rework you think we need to do there. >>> >>> Well there's three locks >> >> It's likely me. >> >> There is one lock for the recv CTB, one for the send CTB, one for the >> list of read messages ready to post process - do you want to use single >> lock for both CTBs or single lock for all cases in CT ? >> >> Michal >> >> disclaimer: outstanding_g2h are not part of the CTB layer > > Why? Like apparently there's not enough provided by that right now, so > Matt is now papering over that gap with more book-keeping in the next > layer. If the layer is not doing a good job it's either the wrong layer, > or shouldn't be a layer. Note that all "outstanding g2h" used by Matt are kind of unsolicited "event" messages received from the GuC, that CTB layer is unable correlate. CTB only tracks "requests" messages for which "response" (or "error") reply is expected. Thus if CTB client is expecting some extra message for its previous communication with GuC, it must track it on its own, as only client knows where in the CTB message payload, actual correlation data (like context ID) is stored. > > And yeah the locking looks like serious amounts of overkill, was it > benchmarked that we need the 3 separate locks for this? I'm not aware of any (micro)benchmarking, but definitely we need some, we were just gradually moving from single threaded blocking CTB calls (waiting for CTB descriptor updates under mutex) to non-blocking calls (protecting only reads/writes to CTB descriptors with spinlock - to allow CTB usage from tasklet/irq). And I was just assuming that we can sacrifice few more integers [1] and have dedicated spinlocks and avoid early over-optimization. > > While reading ctb code I also noticed that a bunch of stuff is checked > before we grab the relevant spinlocks, and it's not > - wrapped in a WARN_ON or GEM_BUG_ON or similar to just check everything > works as expected > - there's no other locks > > So either racy, buggy or playing some extremely clever tricks. None of > which is very good. I'm open to improve that code as needed, but maybe in exchange and to increase motivation please provide feedback on already posted fixes [2] ;) Michal [1] https://elixir.bootlin.com/linux/latest/source/arch/ia64/include/asm/spinlock_types.h#L10 [2] https://patchwork.freedesktop.org/series/92118/ > -Daniel > >> >> >>> there plus it leaks out (you have your >>> outstanding_submission_g2h atomic_t which is very closed tied to well, >>> outstanding guc transmissions), so I guess I need someone else for that? >>> >
Re: [Intel-gfx] [PATCH 2/4] drm/i915/guc: Print error name on CTB (de)registration failure
On 18.08.2021 16:20, Daniel Vetter wrote: > On Thu, Jul 01, 2021 at 05:55:11PM +0200, Michal Wajdeczko wrote: >> Instead of plain error value (%d) print more user friendly error >> name (%pe). >> >> Signed-off-by: Michal Wajdeczko >> --- >> drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 8 >> 1 file changed, 4 insertions(+), 4 deletions(-) >> >> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> index a26bb55c0898..18d52c39f0c2 100644 >> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> @@ -167,8 +167,8 @@ static int ct_register_buffer(struct intel_guc_ct *ct, >> u32 type, >> err = guc_action_register_ct_buffer(ct_to_guc(ct), type, >> desc_addr, buff_addr, size); >> if (unlikely(err)) >> -CT_ERROR(ct, "Failed to register %s buffer (err=%d)\n", >> - guc_ct_buffer_type_to_str(type), err); >> +CT_ERROR(ct, "Failed to register %s buffer (%pe)\n", >> + guc_ct_buffer_type_to_str(type), ERR_PTR(err)); > > errname() is what you want here, not this convoluted jumping through hoops > to fake an error pointer. nope, I was already trying that shortcut, but errname() is not exported so we fail with ERROR: modpost: "errname" [drivers/gpu/drm/i915/i915.ko] undefined! so unless we add that export we must follow initial approach [1] -Michal [1] https://cgit.freedesktop.org/drm/drm-tip/commit/?id=57f5677e535ba24b8926a7125be2ef8d7f09323c > > With that: Reviewed-by: Daniel Vetter >> return err; >> } >> >> @@ -195,8 +195,8 @@ static int ct_deregister_buffer(struct intel_guc_ct *ct, >> u32 type) >> int err = guc_action_deregister_ct_buffer(ct_to_guc(ct), type); >> >> if (unlikely(err)) >> -CT_ERROR(ct, "Failed to deregister %s buffer (err=%d)\n", >> - guc_ct_buffer_type_to_str(type), err); >> +CT_ERROR(ct, "Failed to deregister %s buffer (%pe)\n", >> + guc_ct_buffer_type_to_str(type), ERR_PTR(err)); >> return err; >> } >> >> -- >> 2.25.1 >> >> ___ >> Intel-gfx mailing list >> intel-...@lists.freedesktop.org >> https://lists.freedesktop.org/mailman/listinfo/intel-gfx >
Re: [Intel-gfx] [PATCH 2/4] drm/i915/guc: Print error name on CTB (de)registration failure
On 18.08.2021 18:35, Daniel Vetter wrote: > On Wed, Aug 18, 2021 at 5:11 PM Michal Wajdeczko > wrote: >> >> >> >> On 18.08.2021 16:20, Daniel Vetter wrote: >>> On Thu, Jul 01, 2021 at 05:55:11PM +0200, Michal Wajdeczko wrote: >>>> Instead of plain error value (%d) print more user friendly error >>>> name (%pe). >>>> >>>> Signed-off-by: Michal Wajdeczko >>>> --- >>>> drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 8 >>>> 1 file changed, 4 insertions(+), 4 deletions(-) >>>> >>>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >>>> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >>>> index a26bb55c0898..18d52c39f0c2 100644 >>>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >>>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >>>> @@ -167,8 +167,8 @@ static int ct_register_buffer(struct intel_guc_ct *ct, >>>> u32 type, >>>> err = guc_action_register_ct_buffer(ct_to_guc(ct), type, >>>> desc_addr, buff_addr, size); >>>> if (unlikely(err)) >>>> -CT_ERROR(ct, "Failed to register %s buffer (err=%d)\n", >>>> - guc_ct_buffer_type_to_str(type), err); >>>> +CT_ERROR(ct, "Failed to register %s buffer (%pe)\n", >>>> + guc_ct_buffer_type_to_str(type), ERR_PTR(err)); >>> >>> errname() is what you want here, not this convoluted jumping through hoops >>> to fake an error pointer. >> >> nope, I was already trying that shortcut, but errname() is not exported >> so we fail with >> >> ERROR: modpost: "errname" [drivers/gpu/drm/i915/i915.ko] undefined! >> >> so unless we add that export we must follow initial approach [1] > > Then we export that function. This is all open source, we can actually > fix things up, there should _never_ be a need to hack around things > like this. simple export might be not sufficient, as this function returns NULL for unrecognized error codes, and it might be hard to print that code in plain format, as it %pe does it for us for free. is that big problem to use ERR_PTR? I'm not the only/first one see drivers/net/can/usb/etas_es58x/es58x_core.c drivers/net/ethernet/freescale/enetc/enetc_pf.c drivers/net/phy/phylink.c ... > > And yes I'm keenly aware that there's a pile of i915-gem code which > outright flaunts this principle, but that doesn't mean we should > continue with that. scripts/get_maintainers.pl can help with finding > all the people you need to cc on that export patch. I'm perfectly fine with updating/fixing shared code (did that before, have few more ideas on my todo-list) but in this case I'm not so sure -Michal > -Daniel > >> >> -Michal >> >> [1] >> https://cgit.freedesktop.org/drm/drm-tip/commit/?id=57f5677e535ba24b8926a7125be2ef8d7f09323c >> >>> >>> With that: Reviewed-by: Daniel Vetter >>>> return err; >>>> } >>>> >>>> @@ -195,8 +195,8 @@ static int ct_deregister_buffer(struct intel_guc_ct >>>> *ct, u32 type) >>>> int err = guc_action_deregister_ct_buffer(ct_to_guc(ct), type); >>>> >>>> if (unlikely(err)) >>>> -CT_ERROR(ct, "Failed to deregister %s buffer (err=%d)\n", >>>> - guc_ct_buffer_type_to_str(type), err); >>>> +CT_ERROR(ct, "Failed to deregister %s buffer (%pe)\n", >>>> + guc_ct_buffer_type_to_str(type), ERR_PTR(err)); >>>> return err; >>>> } >>>> >>>> -- >>>> 2.25.1 >>>> >>>> ___ >>>> Intel-gfx mailing list >>>> intel-...@lists.freedesktop.org >>>> https://lists.freedesktop.org/mailman/listinfo/intel-gfx >>> > > >
Re: [RFC PATCH 20/97] drm/i915/guc: Introduce unified HXG messages
On 11.05.2021 17:16, Daniel Vetter wrote: > On Thu, May 06, 2021 at 12:13:34PM -0700, Matthew Brost wrote: >> From: Michal Wajdeczko >> >> New GuC firmware will unify format of MMIO and CTB H2G messages. >> Introduce their definitions now to allow gradual transition of >> our code to match new changes. >> >> Signed-off-by: Michal Wajdeczko >> Signed-off-by: Matthew Brost >> Cc: Michał Winiarski >> --- >> .../gpu/drm/i915/gt/uc/abi/guc_messages_abi.h | 226 ++ >> 1 file changed, 226 insertions(+) >> >> diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h >> b/drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h >> index 775e21f3058c..1c264819aa03 100644 >> --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h >> +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h >> @@ -6,6 +6,232 @@ >> #ifndef _ABI_GUC_MESSAGES_ABI_H >> #define _ABI_GUC_MESSAGES_ABI_H >> >> +/** >> + * DOC: HXG Message > > These aren't useful if we don't pull them in somewhere in the > Documentation/gpu hierarchy. General comment, and also please check that > it all renders correctly still. Patch that connects all these DOC sections into i915.rst is still on private branch, where I'm trying to verify all html rendering, and ... > > btw if you respin a patch not originally by you we generally add a (v1) to > the original s-o-b line (or whever the version split was) and explain in > the usual changelog in the commit message what was changed. > > This holds for the entire series ofc. > -Daniel > >> + * >> + * All messages exchanged with GuC are defined using 32 bit dwords. >> + * First dword is treated as a message header. Remaining dwords are >> optional. >> + * >> + * .. _HXG Message: where such workarounds from early documentation are already removed, since they are not needed any more starting from commit ef09989594bf ("scripts/kernel-doc: add internal hyperlink to DOC: sections") Michal >> + * >> + * >> +---+---+--+ >> + * | | Bits | Description >>| >> + * >> +===+===+==+ >> + * | | | >>| >> + * | 0 |31 | **ORIGIN** - originator of the message >>| >> + * | | | - _`GUC_HXG_ORIGIN_HOST` = 0 >>| >> + * | | | - _`GUC_HXG_ORIGIN_GUC` = 1 >>| >> + * | | | >>| >> + * | >> +---+--+ >> + * | | 30:28 | **TYPE** - message type >>| >> + * | | | - _`GUC_HXG_TYPE_REQUEST` = 0 >>| >> + * | | | - _`GUC_HXG_TYPE_EVENT` = 1 >>| >> + * | | | - _`GUC_HXG_TYPE_NO_RESPONSE_BUSY` = 3 >>| >> + * | | | - _`GUC_HXG_TYPE_NO_RESPONSE_RETRY` = 5 >>| >> + * | | | - _`GUC_HXG_TYPE_RESPONSE_FAILURE` = 6 >>| >> + * | | | - _`GUC_HXG_TYPE_RESPONSE_SUCCESS` = 7 >>| >> + * | >> +---+--+ >> + * | | 27:0 | **AUX** - auxiliary data (depends TYPE) >>| >> + * >> +---+---+--+ >> + * | 1 | 31:0 | optional payload (depends on TYPE) >>| >> + * +---+---+ >>| >> + * |...| | >>| >> + * +---+---+ >>| >> + * | n | 31:0 | >>| >> + * >> +---+---+--+ >> + */ >> + >> +#define GUC_HXG_MSG_MIN_LEN 1u >> +#define GUC_HXG_MSG_0_ORIGIN(0x1 << 31) >> +#define GUC_HXG_ORIGIN_HOST 0u >> +#define GUC_HXG_ORIGIN_GUC
Re: [PATCH 4/7] drm/i915/guc: Add non blocking CTB send function
On 28.06.2021 01:14, Matthew Brost wrote: > Add non blocking CTB send function, intel_guc_send_nb. GuC submission > will send CTBs in the critical path and does not need to wait for these > CTBs to complete before moving on, hence the need for this new function. > > The non-blocking CTB now must have a flow control mechanism to ensure > the buffer isn't overrun. A lazy spin wait is used as we believe the > flow control condition should be rare with a properly sized buffer. > > The function, intel_guc_send_nb, is exported in this patch but unused. > Several patches later in the series make use of this function. > > v2: > (Michal) > - Use define for H2G room calculations > - Move INTEL_GUC_SEND_NB define > (Daniel Vetter) > - Use msleep_interruptible rather than cond_resched > > Signed-off-by: John Harrison > Signed-off-by: Matthew Brost > --- > .../gt/uc/abi/guc_communication_ctb_abi.h | 3 +- > drivers/gpu/drm/i915/gt/uc/intel_guc.h| 11 ++- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 90 +-- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h | 4 +- > 4 files changed, 94 insertions(+), 14 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h > b/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h > index e933ca02d0eb..99e1fad5ca20 100644 > --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h > +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h > @@ -79,7 +79,8 @@ static_assert(sizeof(struct guc_ct_buffer_desc) == 64); > * > +---+---+--+ > */ > > -#define GUC_CTB_MSG_MIN_LEN 1u > +#define GUC_CTB_HDR_LEN 1u > +#define GUC_CTB_MSG_MIN_LEN GUC_CTB_HDR_LEN if you insist to use dedicated macro for the CTB header len then to be consistent you need rename header bitfield macros as well, thus sections/tables will look like: /** * DOC: CTB Message * * +---+---+-+ * | | Bits | Description | * +===+===+=+ * | 0 | 31:0 | `CTB Header`_ | * +---+---+-+ * | 1 | 31:0 | +---+ | * +---+---+ | | | * |...| | | CTB Payload | | * +---+---+ | | | * | n | 31:0 | +---+ | * +---+---+-+ */ /** * DOC: CTB Header * * +---+---+-+ * | | Bits | Description | * +===+===+=+ * | 0 | 31:16 | **FENCE** - ... | * | +---+-+ * | | 15:12 | **FORMAT** - ...| * | +---+-+ * | | 11:8 | **RESERVED**| * | +---+-+ * | | 7:0 | **NUM_DWORDS** - ...| * +---+---+-+ */ #define GUC_CTB_HDR_0_FENCE (0x << 16) #define GUC_CTB_HDR_0_FORMAT(0xf << 12) #define GUC_CTB_FORMAT_HXG0u #define GUC_CTB_HDR_0_RESERVED (0xf << 8) #define GUC_CTB_HDR_0_NUM_DWORDS(0xff << 0) #define GUC_CTB_MAX_DWORDS255u #define GUC_CTB_MSG_MIN_LEN GUC_CTB_HDR_LEN #define GUC_CTB_MSG_MAX_LEN (GUC_CTB_HDR_LEN + GUC_CTB_MAX_DWORDS) alternatively leave ABI defs as-as and just move your HDR definition out of ABI headers to inteL_guc_fwif.h as: #define GUC_CTB_HDR_LEN GUC_CTB_MSG_MIN_LEN > #define GUC_CTB_MSG_MAX_LEN 256u > #define GUC_CTB_MSG_0_FENCE (0x << 16) > #define GUC_CTB_MSG_0_FORMAT (0xf << 12) > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > index 4abc59f6f3cd..efc690fc8fb1 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > @@ -74,7 +74,14 @@ static inline struct intel_guc *log_to_guc(struct > intel_guc_log *log) > static > inline int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len) > { > - return intel_guc_ct_send(&guc->ct, action, len, NULL, 0); > + return intel_guc_ct_send(&guc->ct, action, len, NULL, 0, 0); > +} > + > +static > +inline int intel_guc_send_nb(struct intel_guc *guc, const u32 *action, u32 > len) > +{ > + return intel_guc_ct_send(&guc->ct, action, len, NULL, 0, > + INTEL_GUC_SEND_NB); > } > > static inline int > @@ -82,7 +89,7 @@ intel_guc_send_and_receive(struct intel_guc *guc, const u32
Re: [PATCH 5/7] drm/i915/guc: Add stall timer to non blocking CTB send function
On 28.06.2021 01:14, Matthew Brost wrote: > Implement a stall timer which fails H2G CTBs once a period of time > with no forward progress is reached to prevent deadlock. > > v2: > (Michal) > - Improve error message in ct_deadlock() > - Set broken when ct_deadlock() returns true > - Return -EPIPE on ct_deadlock() > > Signed-off-by: John Harrison > Signed-off-by: Daniele Ceraolo Spurio > Signed-off-by: Matthew Brost > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 62 --- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h | 4 ++ > 2 files changed, 59 insertions(+), 7 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > index 90ee95a240e8..8f553f7f9619 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > @@ -319,6 +319,7 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct) > goto err_deregister; > > ct->enabled = true; > + ct->stall_time = KTIME_MAX; > > return 0; > > @@ -391,9 +392,6 @@ static int ct_write(struct intel_guc_ct *ct, > u32 *cmds = ctb->cmds; > unsigned int i; > > - if (unlikely(ctb->broken)) > - return -EPIPE; > - > if (unlikely(desc->status)) > goto corrupted; > > @@ -509,6 +507,25 @@ static int wait_for_ct_request_update(struct ct_request > *req, u32 *status) > return err; > } > > +#define GUC_CTB_TIMEOUT_MS 1500 > +static inline bool ct_deadlocked(struct intel_guc_ct *ct) > +{ > + long timeout = GUC_CTB_TIMEOUT_MS; > + bool ret = ktime_ms_delta(ktime_get(), ct->stall_time) > timeout; > + > + if (unlikely(ret)) { > + struct guc_ct_buffer_desc *send = ct->ctbs.send.desc; > + struct guc_ct_buffer_desc *recv = ct->ctbs.send.desc; > + > + CT_ERROR(ct, "Communication stalled for %lld, desc > status=%#x,%#x\n", nit: missing unit in "stalled for ... ms" > + ktime_ms_delta(ktime_get(), ct->stall_time), > + send->status, recv->status); > + ct->ctbs.send.broken = true; > + } > + > + return ret; > +} > + > static inline bool h2g_has_room(struct intel_guc_ct_buffer *ctb, u32 len_dw) > { > struct guc_ct_buffer_desc *desc = ctb->desc; > @@ -520,6 +537,26 @@ static inline bool h2g_has_room(struct > intel_guc_ct_buffer *ctb, u32 len_dw) > return space >= len_dw; > } > > +static int has_room_nb(struct intel_guc_ct *ct, u32 len_dw) > +{ > + struct intel_guc_ct_buffer *ctb = &ct->ctbs.send; > + > + lockdep_assert_held(&ct->ctbs.send.lock); > + > + if (unlikely(!h2g_has_room(ctb, len_dw))) { > + if (ct->stall_time == KTIME_MAX) > + ct->stall_time = ktime_get(); > + > + if (unlikely(ct_deadlocked(ct))) > + return -EPIPE; > + else > + return -EBUSY; > + } > + > + ct->stall_time = KTIME_MAX; > + return 0; > +} > + > static int ct_send_nb(struct intel_guc_ct *ct, > const u32 *action, > u32 len, > @@ -530,13 +567,14 @@ static int ct_send_nb(struct intel_guc_ct *ct, > u32 fence; > int ret; > > + if (unlikely(ctb->broken)) > + return -EPIPE; > + > spin_lock_irqsave(&ctb->lock, spin_flags); > > - ret = h2g_has_room(ctb, len + GUC_CTB_HDR_LEN); > - if (unlikely(!ret)) { > - ret = -EBUSY; > + ret = has_room_nb(ct, len + GUC_CTB_HDR_LEN); > + if (unlikely(ret)) > goto out; > - } > > fence = ct_get_next_fence(ct); > ret = ct_write(ct, action, len, fence, flags); > @@ -571,6 +609,9 @@ static int ct_send(struct intel_guc_ct *ct, > GEM_BUG_ON(!response_buf && response_buf_size); > might_sleep(); > > + if (unlikely(ctb->broken)) > + return -EPIPE; ok, but likely could be part of ct_can_send/has_room > + > /* >* We use a lazy spin wait loop here as we believe that if the CT >* buffers are sized correctly the flow control condition should be > @@ -579,8 +620,13 @@ static int ct_send(struct intel_guc_ct *ct, > retry: > spin_lock_irqsave(&ctb->lock, flags); > if (unlikely(!h2g_has_room(ctb, len + GUC_CTB_HDR_LEN))) { > + if (ct->stall_time == KTIME_MAX) > + ct->stall_time = ktime_get(); > spin_unlock_irqrestore(&ctb->lock, flags); > > + if (unlikely(ct_deadlocked(ct))) > + return -EPIPE; > + can't we really put all this into one place? static int ct_can_send(struct intel_guc_ct *ct, u32 len_dw, bool wait) { struct intel_guc_ct_buffer *ctb = &ct->ctbs.send; lockdep_assert_held(&ct->ctbs.send.lock); retry: if (ct->broken) return -EPIPE; if (unlikely(!ctb_has_ro
[PATCH 1/4] drm/i915/guc: Verify result from CTB (de)register action
In commit b839a869dfc9 ("drm/i915/guc: Add support for data reporting in GuC responses") we missed the hypothetical case that GuC might return positive non-zero value as success data. While that would be lucky treated as error case, and at the end will result in reporting valid -EIO, in the meantime this value will be passed to ERR_PTR that could be misleading. v2: rebased Reported-by: Dan Carpenter Signed-off-by: Michal Wajdeczko Cc: Dan Carpenter --- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index 43409044528e..a26bb55c0898 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -148,12 +148,15 @@ static int guc_action_register_ct_buffer(struct intel_guc *guc, u32 type, FIELD_PREP(HOST2GUC_REGISTER_CTB_REQUEST_MSG_2_DESC_ADDR, desc_addr), FIELD_PREP(HOST2GUC_REGISTER_CTB_REQUEST_MSG_3_BUFF_ADDR, buff_addr), }; + int ret; GEM_BUG_ON(type != GUC_CTB_TYPE_HOST2GUC && type != GUC_CTB_TYPE_GUC2HOST); GEM_BUG_ON(size % SZ_4K); /* CT registration must go over MMIO */ - return intel_guc_send_mmio(guc, request, ARRAY_SIZE(request), NULL, 0); + ret = intel_guc_send_mmio(guc, request, ARRAY_SIZE(request), NULL, 0); + + return ret > 0 ? -EPROTO : ret; } static int ct_register_buffer(struct intel_guc_ct *ct, u32 type, @@ -177,11 +180,14 @@ static int guc_action_deregister_ct_buffer(struct intel_guc *guc, u32 type) FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, GUC_ACTION_HOST2GUC_DEREGISTER_CTB), FIELD_PREP(HOST2GUC_DEREGISTER_CTB_REQUEST_MSG_1_TYPE, type), }; + int ret; GEM_BUG_ON(type != GUC_CTB_TYPE_HOST2GUC && type != GUC_CTB_TYPE_GUC2HOST); /* CT deregistration must go over MMIO */ - return intel_guc_send_mmio(guc, request, ARRAY_SIZE(request), NULL, 0); + ret = intel_guc_send_mmio(guc, request, ARRAY_SIZE(request), NULL, 0); + + return ret > 0 ? -EPROTO : ret; } static int ct_deregister_buffer(struct intel_guc_ct *ct, u32 type) -- 2.25.1
[PATCH 2/4] drm/i915/guc: Print error name on CTB (de)registration failure
Instead of plain error value (%d) print more user friendly error name (%pe). Signed-off-by: Michal Wajdeczko --- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index a26bb55c0898..18d52c39f0c2 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -167,8 +167,8 @@ static int ct_register_buffer(struct intel_guc_ct *ct, u32 type, err = guc_action_register_ct_buffer(ct_to_guc(ct), type, desc_addr, buff_addr, size); if (unlikely(err)) - CT_ERROR(ct, "Failed to register %s buffer (err=%d)\n", -guc_ct_buffer_type_to_str(type), err); + CT_ERROR(ct, "Failed to register %s buffer (%pe)\n", +guc_ct_buffer_type_to_str(type), ERR_PTR(err)); return err; } @@ -195,8 +195,8 @@ static int ct_deregister_buffer(struct intel_guc_ct *ct, u32 type) int err = guc_action_deregister_ct_buffer(ct_to_guc(ct), type); if (unlikely(err)) - CT_ERROR(ct, "Failed to deregister %s buffer (err=%d)\n", -guc_ct_buffer_type_to_str(type), err); + CT_ERROR(ct, "Failed to deregister %s buffer (%pe)\n", +guc_ct_buffer_type_to_str(type), ERR_PTR(err)); return err; } -- 2.25.1
[PATCH 3/4] drm/i915/guc: Print error name on CTB send failure
Instead of plain error value (%d) print more user friendly error name (%pe). Signed-off-by: Michal Wajdeczko --- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index 18d52c39f0c2..8110586ce1fd 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -580,8 +580,8 @@ int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 *action, u32 len, ret = ct_send(ct, action, len, response_buf, response_buf_size, &status); if (unlikely(ret < 0)) { - CT_ERROR(ct, "Sending action %#x failed (err=%d status=%#X)\n", -action[0], ret, status); + CT_ERROR(ct, "Sending action %#x failed (%pe) status=%#X\n", +action[0], ERR_PTR(ret), status); } else if (unlikely(ret)) { CT_DEBUG(ct, "send action %#x returned %d (%#x)\n", action[0], ret, ret); -- 2.25.1
[PATCH 4/4] drm/i915/guc: Move and improve error message for missed CTB reply
If we timeout waiting for a CT reply we print very simple error message. Improve that and by moving error reporting to the caller we can use CT_ERROR instead of DRM_ERROR and report just fence as error code will be reported later anyway. Signed-off-by: Michal Wajdeczko --- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index 8110586ce1fd..f488a51e1ebe 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -490,9 +490,6 @@ static int wait_for_ct_request_update(struct ct_request *req, u32 *status) err = wait_for(done, 10); #undef done - if (unlikely(err)) - DRM_ERROR("CT: fence %u err %d\n", req->fence, err); - *status = req->status; return err; } @@ -536,8 +533,11 @@ static int ct_send(struct intel_guc_ct *ct, intel_guc_notify(ct_to_guc(ct)); err = wait_for_ct_request_update(&request, status); - if (unlikely(err)) + if (unlikely(err)) { + CT_ERROR(ct, "No response for request %#x (fence %u)\n", +action[0], request.fence); goto unlink; + } if (FIELD_GET(GUC_HXG_MSG_0_TYPE, *status) != GUC_HXG_TYPE_RESPONSE_SUCCESS) { err = -EIO; -- 2.25.1
[PATCH 0/4] drm/i915/guc: Improve CTB error handling
There was a gap in handling MMIO result from CTB (de)registration and while fixing it improve some other error reports. Signed-off-by: Michal Wajdeczko Michal Wajdeczko (4): drm/i915/guc: Verify result from CTB (de)register action drm/i915/guc: Print error name on CTB (de)registration failure drm/i915/guc: Print error name on CTB send failure drm/i915/guc: Move and improve error message for missed CTB reply drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 30 ++- 1 file changed, 18 insertions(+), 12 deletions(-) -- 2.25.1
[PATCH] drm/i915/guc: Improve GuC CTB ABI
Make CTB Header explicit and separate from CTB Message. Signed-off-by: Michal Wajdeczko Cc: Matthew Brost --- .../gt/uc/abi/guc_communication_ctb_abi.h | 51 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 24 - 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h index e933ca02d0eb..90a86759e108 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h @@ -56,8 +56,9 @@ struct guc_ct_buffer_desc { } __packed; static_assert(sizeof(struct guc_ct_buffer_desc) == 64); + /** - * DOC: CTB Message + * DOC: CTB Header * * +---+---+--+ * | | Bits | Description | @@ -71,21 +72,34 @@ static_assert(sizeof(struct guc_ct_buffer_desc) == 64); * | +---+--+ * | | 7:0 | **NUM_DWORDS** - length of the CTB message (w/o header) | * +---+---+--+ - * | 1 | 31:0 | optional (depends on FORMAT) | - * +---+---+ | - * |...| | | - * +---+---+ | - * | n | 31:0 | | + */ + +#define GUC_CTB_HDR_LEN1u +#define GUC_CTB_HDR_0_FENCE(0x << 16) +#define GUC_CTB_HDR_0_FORMAT (0xf << 12) +#define GUC_CTB_FORMAT_HXG 0u +#define GUC_CTB_HDR_0_RESERVED (0xf << 8) +#define GUC_CTB_HDR_0_NUM_DWORDS (0xff << 0) +#define GUC_CTB_MAX_DWORDS 255u + +/** + * DOC: CTB Message + * + * +---+---+--+ + * | | Bits | Description | + * +===+===+==+ + * | 0 | 31:0 | `CTB Header`_ | + * +---+---+--+ + * | 1 | 31:0 | ++ | + * +---+---+ || | + * |...| | | optional payload (depends on FORMAT) | | + * +---+---+ || | + * | n | 31:0 | ++ | * +---+---+--+ */ -#define GUC_CTB_MSG_MIN_LEN1u -#define GUC_CTB_MSG_MAX_LEN256u -#define GUC_CTB_MSG_0_FENCE(0x << 16) -#define GUC_CTB_MSG_0_FORMAT (0xf << 12) -#define GUC_CTB_FORMAT_HXG 0u -#define GUC_CTB_MSG_0_RESERVED (0xf << 8) -#define GUC_CTB_MSG_0_NUM_DWORDS (0xff << 0) +#define GUC_CTB_MSG_MIN_LENGUC_CTB_HDR_LEN +#define GUC_CTB_MSG_MAX_LEN(GUC_CTB_HDR_LEN + GUC_CTB_MAX_DWORDS) /** * DOC: CTB HXG Message @@ -93,13 +107,10 @@ static_assert(sizeof(struct guc_ct_buffer_desc) == 64); * +---+---+--+ * | | Bits | Description | * +===+===+==+ - * | 0 | 31:16 | FENCE | - * | +---+--+ - * | | 15:12 | FORMAT = GUC_CTB_FORMAT_HXG_ | - * | +---+--+ - * | | 11:8 | RESERVED = MBZ | - * | +---+--+ - * | | 7:0 | NUM_DWORDS = length (in dwords) of the embedded HXG message | + * | 0 | 31:0 | `CTB Header`_ with: | + * | | | | + * | | | - FORMAT = GUC_CTB_FORMAT_HXG_ | + * | | | - NUM_DWORDS = **n** | * +---+---+
Re: [PATCH 47/47] drm/i915/guc: Unblock GuC submission on Gen11+
On 02.07.2021 10:13, Martin Peres wrote: > On 01/07/2021 21:24, Martin Peres wrote: > [...] >>> > + i915->params.enable_guc = ENABLE_GUC_LOAD_HUC; > + return; > + } > + > + /* Default: enable HuC authentication and GuC submission */ > + i915->params.enable_guc = ENABLE_GUC_LOAD_HUC | > ENABLE_GUC_SUBMISSION; This seems to be in contradiction with the GuC submission plan which states: "Not enabled by default on any current platforms but can be enabled via modparam enable_guc". >>> >>> I don't believe any current platform gets this point where GuC >>> submission would be enabled by default. The first would be ADL-P which >>> isn't out yet. >> >> Isn't that exactly what the line above does? > > In case you missed this crucial part of the review. Please answer the > above question. I guess there is some misunderstanding here, and I must admit I had similar doubt, but if you look beyond patch diff and check function code you will find that the very condition is: /* Don't enable GuC/HuC on pre-Gen12 */ if (GRAPHICS_VER(i915) < 12) { i915->params.enable_guc = 0; return; } so all pre-Gen12 platforms will continue to have GuC/HuC disabled. Thanks, Michal
Re: [PATCH 47/47] drm/i915/guc: Unblock GuC submission on Gen11+
On 02.07.2021 15:12, Martin Peres wrote: > On 02/07/2021 16:06, Michal Wajdeczko wrote: >> >> >> On 02.07.2021 10:13, Martin Peres wrote: >>> On 01/07/2021 21:24, Martin Peres wrote: >>> [...] >>>>> >>>>>> >>>>>>> + i915->params.enable_guc = ENABLE_GUC_LOAD_HUC; >>>>>>> + return; >>>>>>> + } >>>>>>> + >>>>>>> + /* Default: enable HuC authentication and GuC submission */ >>>>>>> + i915->params.enable_guc = ENABLE_GUC_LOAD_HUC | >>>>>>> ENABLE_GUC_SUBMISSION; >>>>>> >>>>>> This seems to be in contradiction with the GuC submission plan which >>>>>> states: >>>>>> >>>>>> "Not enabled by default on any current platforms but can be >>>>>> enabled via >>>>>> modparam enable_guc". >>>>>> >>>>> >>>>> I don't believe any current platform gets this point where GuC >>>>> submission would be enabled by default. The first would be ADL-P which >>>>> isn't out yet. >>>> >>>> Isn't that exactly what the line above does? >>> >>> In case you missed this crucial part of the review. Please answer the >>> above question. >> >> I guess there is some misunderstanding here, and I must admit I had >> similar doubt, but if you look beyond patch diff and check function code >> you will find that the very condition is: >> >> /* Don't enable GuC/HuC on pre-Gen12 */ >> if (GRAPHICS_VER(i915) < 12) { >> i915->params.enable_guc = 0; >> return; >> } >> >> so all pre-Gen12 platforms will continue to have GuC/HuC disabled. > > Thanks Michal, but then the problem is the other way: how can one enable > it on gen11? this code here converts default GuC auto mode (enable_guc=-1) into per platform desired (tested) GuC/HuC enables. to override that default, you may still use enable_guc=1 to explicitly enable GuC submission and since we also have this code: +static bool __guc_submission_supported(struct intel_guc *guc) +{ + /* GuC submission is unavailable for pre-Gen11 */ + return intel_guc_is_supported(guc) && + INTEL_GEN(guc_to_gt(guc)->i915) >= 11; +} it should work on any Gen11+. Michal > > I like what Daniele was going for here: separating the capability from > the user-requested value, but then it seems the patch stopped half way. > How about never touching the parameter, and having a AND between the two > values to get the effective enable_guc? > > Right now, the code is really confusing :s > > Thanks, > Martin > >> >> Thanks, >> Michal >>
Re: [Intel-gfx] [PATCH 47/47] drm/i915/guc: Unblock GuC submission on Gen11+
On 02.07.2021 10:09, Martin Peres wrote: > On 02/07/2021 10:29, Pekka Paalanen wrote: >> On Thu, 1 Jul 2021 21:28:06 +0200 >> Daniel Vetter wrote: >> >>> On Thu, Jul 1, 2021 at 8:27 PM Martin Peres >>> wrote: >>>> >>>> On 01/07/2021 11:14, Pekka Paalanen wrote: >>>>> On Wed, 30 Jun 2021 11:58:25 -0700 >>>>> John Harrison wrote: >>>>> >>>>>> On 6/30/2021 01:22, Martin Peres wrote: >>>>>>> On 24/06/2021 10:05, Matthew Brost wrote: >>>>>>>> From: Daniele Ceraolo Spurio >>>>>>>> >>>>>>>> Unblock GuC submission on Gen11+ platforms. >>>>>>>> >>>>>>>> Signed-off-by: Michal Wajdeczko >>>>>>>> Signed-off-by: Daniele Ceraolo Spurio >>>>>>>> >>>>>>>> Signed-off-by: Matthew Brost >>>>>>>> --- >>>>>>>> drivers/gpu/drm/i915/gt/uc/intel_guc.h | 1 + >>>>>>>> drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 8 >>>>>>>> drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h | 3 +-- >>>>>>>> drivers/gpu/drm/i915/gt/uc/intel_uc.c | 14 >>>>>>>> +- >>>>>>>> 4 files changed, 19 insertions(+), 7 deletions(-) >>>>>>>> >>>>> >>>>> ... >>>>> >>>>>>>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c >>>>>>>> b/drivers/gpu/drm/i915/gt/uc/intel_uc.c >>>>>>>> index 7a69c3c027e9..61be0aa81492 100644 >>>>>>>> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c >>>>>>>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c >>>>>>>> @@ -34,8 +34,15 @@ static void uc_expand_default_options(struct >>>>>>>> intel_uc *uc) >>>>>>>> return; >>>>>>>> } >>>>>>>> - /* Default: enable HuC authentication only */ >>>>>>>> - i915->params.enable_guc = ENABLE_GUC_LOAD_HUC; >>>>>>>> + /* Intermediate platforms are HuC authentication only */ >>>>>>>> + if (IS_DG1(i915) || IS_ALDERLAKE_S(i915)) { >>>>>>>> + drm_dbg(&i915->drm, "Disabling GuC only due to old >>>>>>>> platform\n"); >>>>>>> >>>>>>> This comment does not seem accurate, given that DG1 is barely >>>>>>> out, and >>>>>>> ADL is not out yet. How about: >>>>>>> >>>>>>> "Disabling GuC on untested platforms"? >>>>>>> >>>>>> Just because something is not in the shops yet does not mean it is >>>>>> new. >>>>>> Technology is always obsolete by the time it goes on sale. >>>>> >>>>> That is a very good reason to not use terminology like "new", "old", >>>>> "current", "modern" etc. at all. >>>>> >>>>> End users like me definitely do not share your interpretation of >>>>> "old". >>>> >>>> Yep, old and new is relative. In the end, what matters is the >>>> validation >>>> effort, which is why I was proposing "untested platforms". >>>> >>>> Also, remember that you are not writing these messages for Intel >>>> engineers, but instead are writing for Linux *users*. >>> >>> It's drm_dbg. Users don't read this stuff, at least not users with no >>> clue what the driver does and stuff like that. >> >> If I had a problem, I would read it, and I have no clue what anything >> of that is. > > Exactly. > > This level of defense for what is clearly a bad *debug* message (at the > very least, the grammar) makes no sense at all! > > I don't want to hear arguments like "Not my patch" from a developer > literally sending the patch to the ML and who added his SoB to the > patch, playing with words, or minimizing the problem of having such a > message. Agree that 'not my patch' is never a good excuse, but equally we can't blame original patch author as patch was updated few times since then. Maybe to avoid confusions and simplify reviews, we could split this patch into two smaller: first one that really unblocks GuC submission on all Gen11+ (see __guc_submission_supported) and second one that updates defaults for Gen12+ (see uc_expand_default_options), as original patch (from ~2019) evolved more than what title/commit message says. Then we can fix all messaging and make sure it's clear and understood. Thanks, Michal > > All of the above are just clear signals for the community to get off > your playground, which is frankly unacceptable. Your email address does > not matter. > > In the spirit of collaboration, your response should have been "Good > catch, how about or ?". This would not have wasted everyone's > time in an attempt to just have it your way. > > My level of confidence in this GuC transition was already low, but you > guys are working hard to shoot yourself in the foot. Trust should be > earned! > > Martin > >> >> >> Thanks, >> pq >> > ___ > Intel-gfx mailing list > intel-...@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 6/7] drm/i915/guc: Optimize CTB writes and reads
On 06.07.2021 21:00, John Harrison wrote: > On 7/1/2021 10:15, Matthew Brost wrote: >> CTB writes are now in the path of command submission and should be >> optimized for performance. Rather than reading CTB descriptor values >> (e.g. head, tail) which could result in accesses across the PCIe bus, >> store shadow local copies and only read/write the descriptor values when >> absolutely necessary. Also store the current space in the each channel >> locally. >> >> v2: >> (Michel) >> - Add additional sanity checks for head / tail pointers >> - Use GUC_CTB_HDR_LEN rather than magic 1 >> >> Signed-off-by: John Harrison >> Signed-off-by: Matthew Brost >> --- >> drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 88 +++ >> drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h | 6 ++ >> 2 files changed, 65 insertions(+), 29 deletions(-) >> >> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> index a9cb7b608520..5b8b4ff609e2 100644 >> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> @@ -130,6 +130,10 @@ static void guc_ct_buffer_desc_init(struct >> guc_ct_buffer_desc *desc) >> static void guc_ct_buffer_reset(struct intel_guc_ct_buffer *ctb) >> { >> ctb->broken = false; >> + ctb->tail = 0; >> + ctb->head = 0; >> + ctb->space = CIRC_SPACE(ctb->tail, ctb->head, ctb->size); >> + >> guc_ct_buffer_desc_init(ctb->desc); >> } >> @@ -383,10 +387,8 @@ static int ct_write(struct intel_guc_ct *ct, >> { >> struct intel_guc_ct_buffer *ctb = &ct->ctbs.send; >> struct guc_ct_buffer_desc *desc = ctb->desc; >> - u32 head = desc->head; >> - u32 tail = desc->tail; >> + u32 tail = ctb->tail; >> u32 size = ctb->size; >> - u32 used; >> u32 header; >> u32 hxg; >> u32 *cmds = ctb->cmds; >> @@ -395,25 +397,22 @@ static int ct_write(struct intel_guc_ct *ct, >> if (unlikely(desc->status)) >> goto corrupted; >> - if (unlikely((tail | head) >= size)) { >> + GEM_BUG_ON(tail > size); >> + >> +#ifdef CONFIG_DRM_I915_DEBUG_GUC >> + if (unlikely(tail != READ_ONCE(desc->tail))) { >> + CT_ERROR(ct, "Tail was modified %u != %u\n", >> + desc->tail, ctb->tail); >> + desc->status |= GUC_CTB_STATUS_MISMATCH; >> + goto corrupted; >> + } >> + if (unlikely((desc->tail | desc->head) >= size)) { >> CT_ERROR(ct, "Invalid offsets head=%u tail=%u (size=%u)\n", >> - head, tail, size); >> + desc->head, desc->tail, size); >> desc->status |= GUC_CTB_STATUS_OVERFLOW; >> goto corrupted; >> } >> - >> - /* >> - * tail == head condition indicates empty. GuC FW does not support >> - * using up the entire buffer to get tail == head meaning full. >> - */ >> - if (tail < head) >> - used = (size - head) + tail; >> - else >> - used = tail - head; >> - >> - /* make sure there is a space including extra dw for the fence */ >> - if (unlikely(used + len + GUC_CTB_HDR_LEN >= size)) >> - return -ENOSPC; >> +#endif >> /* >> * dw0: CT header (including fence) >> @@ -454,7 +453,9 @@ static int ct_write(struct intel_guc_ct *ct, >> write_barrier(ct); >> /* now update descriptor */ >> + ctb->tail = tail; >> WRITE_ONCE(desc->tail, tail); >> + ctb->space -= len + GUC_CTB_HDR_LEN; >> return 0; >> @@ -470,7 +471,7 @@ static int ct_write(struct intel_guc_ct *ct, >> * @req: pointer to pending request >> * @status: placeholder for status >> * >> - * For each sent request, Guc shall send bac CT response message. >> + * For each sent request, GuC shall send back CT response message. >> * Our message handler will update status of tracked request once >> * response message with given fence is received. Wait here and >> * check for valid response status value. >> @@ -526,24 +527,35 @@ static inline bool ct_deadlocked(struct >> intel_guc_ct *ct) >> return ret; >> } >> -static inline bool h2g_has_room(struct intel_guc_ct_buffer *ctb, >> u32 len_dw) >> +static inline bool h2g_has_room(struct intel_guc_ct *ct, u32 len_dw) >> { >> - struct guc_ct_buffer_desc *desc = ctb->desc; >> - u32 head = READ_ONCE(desc->head); >> + struct intel_guc_ct_buffer *ctb = &ct->ctbs.send; >> + u32 head; >> u32 space; >> - space = CIRC_SPACE(desc->tail, head, ctb->size); >> + if (ctb->space >= len_dw) >> + return true; >> + >> + head = READ_ONCE(ctb->desc->head); >> + if (unlikely(head > ctb->size)) { >> + CT_ERROR(ct, "Corrupted descriptor head=%u tail=%u size=%u\n", >> + ctb->desc->head, ctb->desc->tail, ctb->size); >> + ctb->desc->status |= GUC_CTB_STATUS_OVERFLOW; >> + ctb->broken = true; >> + return false; >> + } >> + >> + space = CIRC_SPACE(ctb->tail, head, ctb->size); >> + ct
Re: [PATCH 6/7] drm/i915/guc: Optimize CTB writes and reads
On 06.07.2021 21:19, John Harrison wrote: > On 7/6/2021 12:12, Michal Wajdeczko wrote: >> On 06.07.2021 21:00, John Harrison wrote: >>> On 7/1/2021 10:15, Matthew Brost wrote: >>>> CTB writes are now in the path of command submission and should be >>>> optimized for performance. Rather than reading CTB descriptor values >>>> (e.g. head, tail) which could result in accesses across the PCIe bus, >>>> store shadow local copies and only read/write the descriptor values >>>> when >>>> absolutely necessary. Also store the current space in the each channel >>>> locally. >>>> >>>> v2: >>>> (Michel) >>>> - Add additional sanity checks for head / tail pointers >>>> - Use GUC_CTB_HDR_LEN rather than magic 1 >>>> >>>> Signed-off-by: John Harrison >>>> Signed-off-by: Matthew Brost >>>> --- >>>> drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 88 >>>> +++ >>>> drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h | 6 ++ >>>> 2 files changed, 65 insertions(+), 29 deletions(-) >>>> >>>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >>>> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >>>> index a9cb7b608520..5b8b4ff609e2 100644 >>>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >>>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >>>> @@ -130,6 +130,10 @@ static void guc_ct_buffer_desc_init(struct >>>> guc_ct_buffer_desc *desc) >>>> static void guc_ct_buffer_reset(struct intel_guc_ct_buffer *ctb) >>>> { >>>> ctb->broken = false; >>>> + ctb->tail = 0; >>>> + ctb->head = 0; >>>> + ctb->space = CIRC_SPACE(ctb->tail, ctb->head, ctb->size); >>>> + >>>> guc_ct_buffer_desc_init(ctb->desc); >>>> } >>>> @@ -383,10 +387,8 @@ static int ct_write(struct intel_guc_ct *ct, >>>> { >>>> struct intel_guc_ct_buffer *ctb = &ct->ctbs.send; >>>> struct guc_ct_buffer_desc *desc = ctb->desc; >>>> - u32 head = desc->head; >>>> - u32 tail = desc->tail; >>>> + u32 tail = ctb->tail; >>>> u32 size = ctb->size; >>>> - u32 used; >>>> u32 header; >>>> u32 hxg; >>>> u32 *cmds = ctb->cmds; >>>> @@ -395,25 +397,22 @@ static int ct_write(struct intel_guc_ct *ct, >>>> if (unlikely(desc->status)) >>>> goto corrupted; >>>> - if (unlikely((tail | head) >= size)) { >>>> + GEM_BUG_ON(tail > size); >>>> + >>>> +#ifdef CONFIG_DRM_I915_DEBUG_GUC >>>> + if (unlikely(tail != READ_ONCE(desc->tail))) { >>>> + CT_ERROR(ct, "Tail was modified %u != %u\n", >>>> + desc->tail, ctb->tail); >>>> + desc->status |= GUC_CTB_STATUS_MISMATCH; >>>> + goto corrupted; >>>> + } >>>> + if (unlikely((desc->tail | desc->head) >= size)) { >>>> CT_ERROR(ct, "Invalid offsets head=%u tail=%u (size=%u)\n", >>>> - head, tail, size); >>>> + desc->head, desc->tail, size); >>>> desc->status |= GUC_CTB_STATUS_OVERFLOW; >>>> goto corrupted; >>>> } >>>> - >>>> - /* >>>> - * tail == head condition indicates empty. GuC FW does not support >>>> - * using up the entire buffer to get tail == head meaning full. >>>> - */ >>>> - if (tail < head) >>>> - used = (size - head) + tail; >>>> - else >>>> - used = tail - head; >>>> - >>>> - /* make sure there is a space including extra dw for the fence */ >>>> - if (unlikely(used + len + GUC_CTB_HDR_LEN >= size)) >>>> - return -ENOSPC; >>>> +#endif >>>> /* >>>> * dw0: CT header (including fence) >>>> @@ -454,7 +453,9 @@ static int ct_write(struct intel_guc_ct *ct, >>>> write_barrier(ct); >>>> /* now update descriptor */ >>>> + ctb->tail = tail; >>>> WRITE_ONCE(desc->tail, tail); >>>> + ctb->space -= le
Re: [PATCH 0/2] Update to new HuC for TGL+ and enable GuC/HuC on ADL-P
Hi John, On 26.06.2021 02:45, john.c.harri...@intel.com wrote: > From: John Harrison > > There is a new HuC version available for TGL and compatible platforms, > so switch to using it. Also, there is now a GuC and HuC for ADL-P, so > use those too. I recall discussion about splitting UC_FW meta macro into two: one for GUC firmwares and other for HUC firmwares - what happen to this idea? Maybe we can do it in this series as a first step ? then changing just HuC version will be limited to HUC meta macro only. Michal > > Signed-off-by: John Harrison > > > John Harrison (2): > drm/i915/huc: Update TGL and friends to HuC 7.9.3 > drm/i915/adlp: Add ADL-P GuC/HuC firmware files > > drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 7 --- > 1 file changed, 4 insertions(+), 3 deletions(-) >
Re: [Intel-gfx] [PATCH 47/47] drm/i915/guc: Unblock GuC submission on Gen11+
On 07.07.2021 02:57, John Harrison wrote: > On 7/3/2021 01:21, Martin Peres wrote: >> On 02/07/2021 18:07, Michal Wajdeczko wrote: >>> On 02.07.2021 10:09, Martin Peres wrote: >>>> On 02/07/2021 10:29, Pekka Paalanen wrote: >>>>> On Thu, 1 Jul 2021 21:28:06 +0200 >>>>> Daniel Vetter wrote: >>>>> >>>>>> On Thu, Jul 1, 2021 at 8:27 PM Martin Peres >>>>>> wrote: >>>>>>> >>>>>>> On 01/07/2021 11:14, Pekka Paalanen wrote: >>>>>>>> On Wed, 30 Jun 2021 11:58:25 -0700 >>>>>>>> John Harrison wrote: >>>>>>>>> On 6/30/2021 01:22, Martin Peres wrote: >>>>>>>>>> On 24/06/2021 10:05, Matthew Brost wrote: >>>>>>>>>>> From: Daniele Ceraolo Spurio >>>>>>>>>>> >>>>>>>>>>> Unblock GuC submission on Gen11+ platforms. >>>>>>>>>>> >>>>>>>>>>> Signed-off-by: Michal Wajdeczko >>>>>>>>>>> Signed-off-by: Daniele Ceraolo Spurio >>>>>>>>>>> >>>>>>>>>>> Signed-off-by: Matthew Brost >>>>>>>>>>> --- >>>>>>>>>>> drivers/gpu/drm/i915/gt/uc/intel_guc.h | 1 + >>>>>>>>>>> drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 8 >>>>>>>>>>> drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h | 3 +-- >>>>>>>>>>> drivers/gpu/drm/i915/gt/uc/intel_uc.c | 14 >>>>>>>>>>> +- >>>>>>>>>>> 4 files changed, 19 insertions(+), 7 deletions(-) >>>>>>>> >>>>>>>> ... >>>>>>>>>>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c >>>>>>>>>>> b/drivers/gpu/drm/i915/gt/uc/intel_uc.c >>>>>>>>>>> index 7a69c3c027e9..61be0aa81492 100644 >>>>>>>>>>> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c >>>>>>>>>>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c >>>>>>>>>>> @@ -34,8 +34,15 @@ static void uc_expand_default_options(struct >>>>>>>>>>> intel_uc *uc) >>>>>>>>>>> return; >>>>>>>>>>> } >>>>>>>>>>> - /* Default: enable HuC authentication only */ >>>>>>>>>>> - i915->params.enable_guc = ENABLE_GUC_LOAD_HUC; >>>>>>>>>>> + /* Intermediate platforms are HuC authentication only */ >>>>>>>>>>> + if (IS_DG1(i915) || IS_ALDERLAKE_S(i915)) { >>>>>>>>>>> + drm_dbg(&i915->drm, "Disabling GuC only due to old >>>>>>>>>>> platform\n"); >>>>>>>>>> >>>>>>>>>> This comment does not seem accurate, given that DG1 is barely >>>>>>>>>> out, and >>>>>>>>>> ADL is not out yet. How about: >>>>>>>>>> >>>>>>>>>> "Disabling GuC on untested platforms"? >>>>>>>>> Just because something is not in the shops yet does not mean it is >>>>>>>>> new. >>>>>>>>> Technology is always obsolete by the time it goes on sale. >>>>>>>> >>>>>>>> That is a very good reason to not use terminology like "new", >>>>>>>> "old", >>>>>>>> "current", "modern" etc. at all. >>>>>>>> >>>>>>>> End users like me definitely do not share your interpretation of >>>>>>>> "old". >>>>>>> >>>>>>> Yep, old and new is relative. In the end, what matters is the >>>>>>> validation >>>>>>> effort, which is why I was proposing "untested platforms". >>>>>>> >>>>>>> Also, remember that you are not writing these messages for Intel >>>>>>> engineers, but instead are writing for Linux *users*. >>>>>> >>>>>> It&
Re: [PATCH 06/56] drm/i915/guc: Optimize CTB writes and reads
Hi, On 07.07.2021 21:09, Matthew Brost wrote: > CTB writes are now in the path of command submission and should be > optimized for performance. Rather than reading CTB descriptor values > (e.g. head, tail) which could result in accesses across the PCIe bus, > store shadow local copies and only read/write the descriptor values when > absolutely necessary. Also store the current space in the each channel > locally. > > v2: > (Michal) > - Add additional sanity checks for head / tail pointers > - Use GUC_CTB_HDR_LEN rather than magic 1 > v3: > (Michal / John H) > - Drop redundant check of head value > v4: > (John H) > - Drop redundant checks of tail / head values mostly nits, but since you will be sending it again... > > Signed-off-by: John Harrison > Signed-off-by: Matthew Brost > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 87 ++- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h | 6 ++ > 2 files changed, 61 insertions(+), 32 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > index db3e85b89573..37fe9f3bbce3 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > @@ -130,6 +130,10 @@ static void guc_ct_buffer_desc_init(struct > guc_ct_buffer_desc *desc) > static void guc_ct_buffer_reset(struct intel_guc_ct_buffer *ctb) > { > ctb->broken = false; > + ctb->tail = 0; > + ctb->head = 0; > + ctb->space = CIRC_SPACE(ctb->tail, ctb->head, ctb->size); > + > guc_ct_buffer_desc_init(ctb->desc); > } > > @@ -383,10 +387,8 @@ static int ct_write(struct intel_guc_ct *ct, > { > struct intel_guc_ct_buffer *ctb = &ct->ctbs.send; > struct guc_ct_buffer_desc *desc = ctb->desc; > - u32 head = desc->head; > - u32 tail = desc->tail; > + u32 tail = ctb->tail; > u32 size = ctb->size; > - u32 used; > u32 header; > u32 hxg; > u32 type; > @@ -396,25 +398,22 @@ static int ct_write(struct intel_guc_ct *ct, > if (unlikely(desc->status)) > goto corrupted; > > - if (unlikely((tail | head) >= size)) { > - CT_ERROR(ct, "Invalid offsets head=%u tail=%u (size=%u)\n", > - head, tail, size); > + GEM_BUG_ON(tail > size); > + > +#ifdef CONFIG_DRM_I915_DEBUG_GUC > + if (unlikely(tail != READ_ONCE(desc->tail))) { > + CT_ERROR(ct, "Tail was modified %u != %u\n", > + desc->tail, ctb->tail); here you accessing desc->tail again so maybe we can use: u32 raw __maybe_unused; raw = READ_ONCE(desc->tail); if (unlikely(raw != tail)) ... CT_ERROR(..., raw, tail); > + desc->status |= GUC_CTB_STATUS_MISMATCH; > + goto corrupted; > + } > + if (unlikely(desc->head >= size)) { above you are reading value from desc using READ_ONCE, could be raw = READ_ONCE(desc->head); if (unlikely(raw >= size)) ... CT_ERROR(..., raw, size); > + CT_ERROR(ct, "Invalid offsets head=%u (size=%u)\n", "Invalid head offset %u > %u\n" ? > + desc->head, size); > desc->status |= GUC_CTB_STATUS_OVERFLOW; > goto corrupted; > } > - > - /* > - * tail == head condition indicates empty. GuC FW does not support > - * using up the entire buffer to get tail == head meaning full. > - */ > - if (tail < head) > - used = (size - head) + tail; > - else > - used = tail - head; > - > - /* make sure there is a space including extra dw for the header */ > - if (unlikely(used + len + GUC_CTB_HDR_LEN >= size)) > - return -ENOSPC; > +#endif > > /* >* dw0: CT header (including fence) > @@ -453,7 +452,9 @@ static int ct_write(struct intel_guc_ct *ct, > write_barrier(ct); > > /* now update descriptor */ > + ctb->tail = tail; > WRITE_ONCE(desc->tail, tail); > + ctb->space -= len + GUC_CTB_HDR_LEN; maybe keep ctb updates together? + /* update local copies */ + ctb->tail = tail; + ctb->space -= len + GUC_CTB_HDR_LEN; + /* now update descriptor */ WRITE_ONCE(desc->tail, tail); > > return 0; > > @@ -469,7 +470,7 @@ static int ct_write(struct intel_guc_ct *ct, > * @req: pointer to pending request > * @status: placeholder for status > * > - * For each sent request, Guc shall send bac CT response message. > + * For each sent request, GuC shall send back CT response message. > * Our message handler will update status of tracked request once > * response message with given fence is received. Wait here and > * check for valid response status value. > @@ -525,24 +526,35 @@ static inline bool ct_deadlocked(struct intel_guc_ct > *ct) > return ret; > } > > -static inline bool h2g_has_room(struct intel_guc_ct_buffer *ctb, u32 l
Re: [PATCH 06/7] drm/i915/guc: Optimize CTB writes and reads
On 08.07.2021 01:25, Matthew Brost wrote: > CTB writes are now in the path of command submission and should be > optimized for performance. Rather than reading CTB descriptor values > (e.g. head, tail) which could result in accesses across the PCIe bus, > store shadow local copies and only read/write the descriptor values when > absolutely necessary. Also store the current space in the each channel > locally. > > v2: > (Michal) > - Add additional sanity checks for head / tail pointers > - Use GUC_CTB_HDR_LEN rather than magic 1 > v3: > (Michal / John H) > - Drop redundant check of head value > v4: > (John H) > - Drop redundant checks of tail / head values > v5: > (Michal) > - Address more nits > > Signed-off-by: John Harrison > Signed-off-by: Matthew Brost > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 92 +++ > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h | 6 ++ > 2 files changed, 66 insertions(+), 32 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > index db3e85b89573..d552d3016779 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > @@ -130,6 +130,10 @@ static void guc_ct_buffer_desc_init(struct > guc_ct_buffer_desc *desc) > static void guc_ct_buffer_reset(struct intel_guc_ct_buffer *ctb) > { > ctb->broken = false; > + ctb->tail = 0; > + ctb->head = 0; > + ctb->space = CIRC_SPACE(ctb->tail, ctb->head, ctb->size); > + > guc_ct_buffer_desc_init(ctb->desc); > } > > @@ -383,10 +387,8 @@ static int ct_write(struct intel_guc_ct *ct, > { > struct intel_guc_ct_buffer *ctb = &ct->ctbs.send; > struct guc_ct_buffer_desc *desc = ctb->desc; > - u32 head = desc->head; > - u32 tail = desc->tail; > + u32 tail = ctb->tail; > u32 size = ctb->size; > - u32 used; > u32 header; > u32 hxg; > u32 type; > @@ -396,25 +398,22 @@ static int ct_write(struct intel_guc_ct *ct, > if (unlikely(desc->status)) > goto corrupted; > > - if (unlikely((tail | head) >= size)) { > - CT_ERROR(ct, "Invalid offsets head=%u tail=%u (size=%u)\n", > - head, tail, size); > + GEM_BUG_ON(tail > size); > + > +#ifdef CONFIG_DRM_I915_DEBUG_GUC > + if (unlikely(tail != READ_ONCE(desc->tail))) { > + CT_ERROR(ct, "Tail was modified %u != %u\n", > + desc->tail, tail); > + desc->status |= GUC_CTB_STATUS_MISMATCH; > + goto corrupted; > + } > + if (unlikely(desc->head >= size)) { READ_ONCE wouldn't hurt > + CT_ERROR(ct, "Invalid head offset %u >= %u)\n", > + desc->head, size); > desc->status |= GUC_CTB_STATUS_OVERFLOW; > goto corrupted; > } > - > - /* > - * tail == head condition indicates empty. GuC FW does not support > - * using up the entire buffer to get tail == head meaning full. > - */ > - if (tail < head) > - used = (size - head) + tail; > - else > - used = tail - head; > - > - /* make sure there is a space including extra dw for the header */ > - if (unlikely(used + len + GUC_CTB_HDR_LEN >= size)) > - return -ENOSPC; > +#endif > > /* >* dw0: CT header (including fence) > @@ -452,6 +451,10 @@ static int ct_write(struct intel_guc_ct *ct, >*/ > write_barrier(ct); > > + /* update local copies */ > + ctb->tail = tail; > + ctb->space -= len + GUC_CTB_HDR_LEN; it looks that we rely on previous call to h2g_has_room(), but maybe for completeness we should have sanity check in this function as well: GEM_BUG_ON(ctb->space < len + HDR_LEN); not a blocker, other LGTM, Reviewed-by: Michal Wajdeczko Michal > + > /* now update descriptor */ > WRITE_ONCE(desc->tail, tail); > > @@ -469,7 +472,7 @@ static int ct_write(struct intel_guc_ct *ct, > * @req: pointer to pending request > * @status: placeholder for status > * > - * For each sent request, Guc shall send bac CT response message. > + * For each sent request, GuC shall send back CT response message. > * Our message handler will update status of tracked request once > * response message with given fence is received. Wait here and > * check for valid response status value. > @@ -525,24 +528,36 @@ static inline bool ct_deadlocked(s
Re: [PATCH 02/16] drm/i915/guc/slpc: Initial definitions for slpc
Hi Vinay, On 10.07.2021 03:20, Vinay Belgaumkar wrote: > Add macros to check for slpc support. This feature is currently supported > for gen12+ and enabled whenever guc submission is enabled/selected. please try to use consistent names across all patches: s/slpc/SLPC s/gen12/Gen12 s/guc/GuC > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > Signed-off-by: Daniele Ceraolo Spurio > --- > drivers/gpu/drm/i915/gt/uc/intel_guc.c| 1 + > drivers/gpu/drm/i915/gt/uc/intel_guc.h| 2 ++ > .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 21 +++ > .../gpu/drm/i915/gt/uc/intel_guc_submission.h | 16 ++ > drivers/gpu/drm/i915/gt/uc/intel_uc.c | 6 -- > drivers/gpu/drm/i915/gt/uc/intel_uc.h | 1 + > 6 files changed, 45 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > index 979128e28372..b9a809f2d221 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > @@ -157,6 +157,7 @@ void intel_guc_init_early(struct intel_guc *guc) > intel_guc_ct_init_early(&guc->ct); > intel_guc_log_init_early(&guc->log); > intel_guc_submission_init_early(guc); > + intel_guc_slpc_init_early(guc); > > mutex_init(&guc->send_mutex); > spin_lock_init(&guc->irq_lock); > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > index 5d94cf482516..e5a456918b88 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > @@ -57,6 +57,8 @@ struct intel_guc { > > bool submission_supported; > bool submission_selected; > + bool slpc_supported; > + bool slpc_selected; > > struct i915_vma *ads_vma; > struct __guc_ads_blob *ads_blob; > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > index 9c102bf0c8e3..e2644a05f298 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > @@ -2351,6 +2351,27 @@ void intel_guc_submission_init_early(struct intel_guc > *guc) > guc->submission_selected = __guc_submission_selected(guc); > } > > +static bool __guc_slpc_supported(struct intel_guc *guc) hmm, easy to confuse with intel_guc_slpc_is_supported, so maybe: __detect_slpc_supported() (yes, I know you were following code above) > +{ > + /* GuC slpc is unavailable for pre-Gen12 */ s/slpc/SLPC > + return guc->submission_supported && > + GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12; > +} > + > +static bool __guc_slpc_selected(struct intel_guc *guc) > +{ > + if (!intel_guc_slpc_is_supported(guc)) > + return false; > + > + return guc->submission_selected; > +} > + > +void intel_guc_slpc_init_early(struct intel_guc *guc) > +{ > + guc->slpc_supported = __guc_slpc_supported(guc); > + guc->slpc_selected = __guc_slpc_selected(guc); > +} in patch 4/16 you are introducing intel_guc_slpc.c|h so to have proper encapsulation better to define this function as void intel_guc_slpc_init_early(struct intel_guc_slpc *slpc) { } and move it to intel_guc_slpc.c > + > static inline struct intel_context * > g2h_context_lookup(struct intel_guc *guc, u32 desc_idx) > { > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h > index be767eb6ff71..7ae5fd052faf 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h > @@ -13,6 +13,7 @@ > struct drm_printer; > struct intel_engine_cs; > > +void intel_guc_slpc_init_early(struct intel_guc *guc); it really does not belong to this .h > void intel_guc_submission_init_early(struct intel_guc *guc); > int intel_guc_submission_init(struct intel_guc *guc); > void intel_guc_submission_enable(struct intel_guc *guc); > @@ -50,4 +51,19 @@ static inline bool intel_guc_submission_is_used(struct > intel_guc *guc) > return intel_guc_is_used(guc) && intel_guc_submission_is_wanted(guc); > } > > +static inline bool intel_guc_slpc_is_supported(struct intel_guc *guc) > +{ > + return guc->slpc_supported; > +} > + > +static inline bool intel_guc_slpc_is_wanted(struct intel_guc *guc) > +{ > + return guc->slpc_selected; > +} > + > +static inline bool intel_guc_slpc_is_used(struct intel_guc *guc) > +{ > + return intel_guc_submission_is_used(guc) && > intel_guc_slpc_is_wanted(guc); > +} did you try to define them in intel_guc_slpc.h ? note that to avoid circular dependencies you can define slpc struct in intel_guc_slpc_types.h and then in intel_guc.h: #include "intel_guc_slpc_types.h" instead of intel_guc_slpc.h in intel_guc_slpc.h: #include "intel_guc.h" #include "intel_guc_slpc_types.h" #include "intel_guc_sub
Re: [Intel-gfx] [PATCH 04/16] drm/i915/guc/slpc: Lay out slpc init/enable/disable/fini
On 10.07.2021 03:20, Vinay Belgaumkar wrote: > Declare header and source files for SLPC, along with init and > enable/disable function templates. later you claim that "disable" is not needed > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > drivers/gpu/drm/i915/Makefile | 1 + > drivers/gpu/drm/i915/gt/uc/intel_guc.h | 2 ++ > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 34 + > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 16 ++ > 4 files changed, 53 insertions(+) > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile > index ab7679957623..d8eac4468df9 100644 > --- a/drivers/gpu/drm/i915/Makefile > +++ b/drivers/gpu/drm/i915/Makefile > @@ -186,6 +186,7 @@ i915-y += gt/uc/intel_uc.o \ > gt/uc/intel_guc_fw.o \ > gt/uc/intel_guc_log.o \ > gt/uc/intel_guc_log_debugfs.o \ > + gt/uc/intel_guc_slpc.o \ > gt/uc/intel_guc_submission.o \ > gt/uc/intel_huc.o \ > gt/uc/intel_huc_debugfs.o \ > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > index e5a456918b88..0dbbd9cf553f 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > @@ -15,6 +15,7 @@ > #include "intel_guc_ct.h" > #include "intel_guc_log.h" > #include "intel_guc_reg.h" > +#include "intel_guc_slpc.h" > #include "intel_uc_fw.h" > #include "i915_utils.h" > #include "i915_vma.h" > @@ -30,6 +31,7 @@ struct intel_guc { > struct intel_uc_fw fw; > struct intel_guc_log log; > struct intel_guc_ct ct; > + struct intel_guc_slpc slpc; > > /* Global engine used to submit requests to GuC */ > struct i915_sched_engine *sched_engine; > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > new file mode 100644 > index ..c1f569d2300d > --- /dev/null > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -0,0 +1,34 @@ > +/* > + * SPDX-License-Identifier: MIT SPDX tag shall be in very first line, for .c: // SPDX-License-Identifier: MIT > + * > + * Copyright © 2020 Intel Corporation 2021 > + */ > + > +#include "intel_guc_slpc.h" > + > +int intel_guc_slpc_init(struct intel_guc_slpc *slpc) > +{ > + return 0; > +} > + > +/* > + * intel_guc_slpc_enable() - Start SLPC > + * @slpc: pointer to intel_guc_slpc. > + * > + * SLPC is enabled by setting up the shared data structure and > + * sending reset event to GuC SLPC. Initial data is setup in > + * intel_guc_slpc_init. Here we send the reset event. We do > + * not currently need a slpc_disable since this is taken care > + * of automatically when a reset/suspend occurs and the guc s/guc/GuC > + * channels are destroyed. you mean CTB ? > + * > + * Return: 0 on success, non-zero error code on failure. > + */ > +int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) > +{ > + return 0; > +} > + > +void intel_guc_slpc_fini(struct intel_guc_slpc *slpc) > +{ > +} > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > new file mode 100644 > index ..74fd86769163 > --- /dev/null > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > @@ -0,0 +1,16 @@ > +/* > + * SPDX-License-Identifier: MIT SPDX tag shall be in very first line, for .h: /* SPDX-License-Identifier: MIT */ > + * > + * Copyright © 2020 Intel Corporation 2021 > + */ > +#ifndef _INTEL_GUC_SLPC_H_ > +#define _INTEL_GUC_SLPC_H_ > + > +struct intel_guc_slpc { > +}; move all data definitions to intel_guc_slpc_types.h and include it here > + > +int intel_guc_slpc_init(struct intel_guc_slpc *slpc); > +int intel_guc_slpc_enable(struct intel_guc_slpc *slpc); > +void intel_guc_slpc_fini(struct intel_guc_slpc *slpc); > + > +#endif > and as suggested in comment to 2/14 you should likely move this patch to the front of the series Michal
Re: [PATCH 05/16] drm/i915/guc/slpc: Adding slpc communication interfaces
On 10.07.2021 03:20, Vinay Belgaumkar wrote: > Replicate the SLPC header file in GuC for the most part. There are what you mean by "replicate" here? > some SLPC mode based parameters which haven't been included since > we are not using them. > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > drivers/gpu/drm/i915/gt/uc/intel_guc.c| 4 + > drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 2 + > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 2 + > .../gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h | 255 ++ > 4 files changed, 263 insertions(+) > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > index b9a809f2d221..9d61b2d54de4 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > @@ -202,11 +202,15 @@ static u32 guc_ctl_debug_flags(struct intel_guc *guc) > > static u32 guc_ctl_feature_flags(struct intel_guc *guc) > { > + struct intel_gt *gt = guc_to_gt(guc); > u32 flags = 0; > > if (!intel_guc_submission_is_used(guc)) > flags |= GUC_CTL_DISABLE_SCHEDULER; > > + if (intel_uc_uses_guc_slpc(>->uc)) > + flags |= GUC_CTL_ENABLE_SLPC; > + > return flags; > } > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h > index 94bb1ca6f889..19e2504d7a36 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h > @@ -114,6 +114,8 @@ > #define GUC_ADS_ADDR_SHIFT 1 > #define GUC_ADS_ADDR_MASK (0xF << GUC_ADS_ADDR_SHIFT) > > +#define GUC_CTL_ENABLE_SLPCBIT(2) this should be defined closer to GUC_CTL_FEATURE > + > #define GUC_CTL_MAX_DWORDS (SOFT_SCRATCH_COUNT - 2) /* [1..14] */ > > /* Generic GT SysInfo data types */ > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > index 74fd86769163..98036459a1a3 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > @@ -6,6 +6,8 @@ > #ifndef _INTEL_GUC_SLPC_H_ > #define _INTEL_GUC_SLPC_H_ > > +#include "intel_guc_slpc_fwif.h" doesn't seem to be needed right now > + > struct intel_guc_slpc { > }; > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h > new file mode 100644 > index ..2a5e71428374 > --- /dev/null > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_fwif.h I've started to move all pure ABI definitions to files in abi/ folder, leaving in guc_fwif.h only our next level helpers/wrappers. Can you move these SLPC definition there too ? maybe as dedicated: abi/guc_slpc_abi.h > @@ -0,0 +1,255 @@ > +/* > + * SPDX-License-Identifier: MIT use proper format > + * > + * Copyright © 2020 Intel Corporation 2021 > + */ > +#ifndef _INTEL_GUC_SLPC_FWIF_H_ > +#define _INTEL_GUC_SLPC_FWIF_H_ > + > +#include > + > +/* This file replicates the header in GuC code for handling SLPC related > + * data structures and sizes > + */ use proper format for multi-line comments: /* * blah blah * blah blah */ > + > +/* SLPC exposes certain parameters for global configuration by the host. > + * These are referred to as override parameters, because in most cases > + * the host will not need to modify the default values used by SLPC. > + * SLPC remembers the default values which allows the host to easily restore > + * them by simply unsetting the override. The host can set or unset override > + * parameters during SLPC (re-)initialization using the SLPC Reset event. > + * The host can also set or unset override parameters on the fly using the > + * Parameter Set and Parameter Unset events > + */ > +#define SLPC_MAX_OVERRIDE_PARAMETERS 256 > +#define SLPC_OVERRIDE_BITFIELD_SIZE \ > + (SLPC_MAX_OVERRIDE_PARAMETERS / 32) > + > +#define SLPC_PAGE_SIZE_BYTES 4096 > +#define SLPC_CACHELINE_SIZE_BYTES64 > +#define SLPC_SHARE_DATA_SIZE_BYTE_HEADER SLPC_CACHELINE_SIZE_BYTES > +#define SLPC_SHARE_DATA_SIZE_BYTE_PLATFORM_INFO > SLPC_CACHELINE_SIZE_BYTES > +#define SLPC_SHARE_DATA_SIZE_BYTE_TASK_STATE SLPC_CACHELINE_SIZE_BYTES > +#define SLPC_SHARE_DATA_MODE_DEFN_TABLE_SIZE SLPC_PAGE_SIZE_BYTES can you put some simply diagram that would describe this layout ? > + > +#define SLPC_SHARE_DATA_SIZE_BYTE_MAX(2 * > SLPC_PAGE_SIZE_BYTES) > + > +/* Cacheline size aligned (Total size needed for > + * SLPM_KMD_MAX_OVERRIDE_PARAMETERS=256 is 1088 bytes) > + */ > +#define SLPC_SHARE_DATA_SIZE_BYTE_PARAM > (SLPC_MAX_OVERRIDE_PARAMETERS * 4) \ > + + > ((SLPC_MAX_OVERRIDE_PARAMETERS / 32) * 4)) \ > +
Re: [PATCH 06/16] drm/i915/guc/slpc: Allocate, initialize and release slpc
On 10.07.2021 03:20, Vinay Belgaumkar wrote: > Allocate data structures for SLPC and functions for > initializing on host side. > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > drivers/gpu/drm/i915/gt/uc/intel_guc.c | 11 +++ > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 36 - > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 20 > 3 files changed, 66 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > index 9d61b2d54de4..82863a9bc8e8 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > @@ -336,6 +336,12 @@ int intel_guc_init(struct intel_guc *guc) > goto err_ct; > } > > + if (intel_guc_slpc_is_used(guc)) { > + ret = intel_guc_slpc_init(&guc->slpc); > + if (ret) > + goto err_submission; > + } > + > /* now that everything is perma-pinned, initialize the parameters */ > guc_init_params(guc); > > @@ -346,6 +352,8 @@ int intel_guc_init(struct intel_guc *guc) > > return 0; > > +err_submission: > + intel_guc_submission_fini(guc); > err_ct: > intel_guc_ct_fini(&guc->ct); > err_ads: > @@ -368,6 +376,9 @@ void intel_guc_fini(struct intel_guc *guc) > > i915_ggtt_disable_guc(gt->ggtt); > > + if (intel_guc_slpc_is_used(guc)) > + intel_guc_slpc_fini(&guc->slpc); > + > if (intel_guc_submission_is_used(guc)) > intel_guc_submission_fini(guc); > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index c1f569d2300d..94e2f19951aa 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -4,11 +4,41 @@ > * Copyright © 2020 Intel Corporation > */ > > +#include hmm, what exactly is needed from this header ? > + > +#include "gt/intel_gt.h" > +#include "gt/intel_rps.h" > + > +#include "i915_drv.h" > #include "intel_guc_slpc.h" > +#include "intel_pm.h" > + > +static inline struct intel_guc *slpc_to_guc(struct intel_guc_slpc *slpc) > +{ > + return container_of(slpc, struct intel_guc, slpc); > +} > + > +static int slpc_shared_data_init(struct intel_guc_slpc *slpc) > +{ > + struct intel_guc *guc = slpc_to_guc(slpc); > + int err; > + u32 size = PAGE_ALIGN(sizeof(struct slpc_shared_data)); move err decl here > + > + err = intel_guc_allocate_and_map_vma(guc, size, &slpc->vma, > &slpc->vaddr); > + if (unlikely(err)) { > + DRM_ERROR("Failed to allocate slpc struct (err=%d)\n", err); s/slpc/SLPC and use drm_err instead and you may also want to print error as %pe > + i915_vma_unpin_and_release(&slpc->vma, I915_VMA_RELEASE_MAP); do you really need this ? > + return err; > + } > + > + return err; > +} > > int intel_guc_slpc_init(struct intel_guc_slpc *slpc) > { > - return 0; > + GEM_BUG_ON(slpc->vma); > + > + return slpc_shared_data_init(slpc); > } > > /* > @@ -31,4 +61,8 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) > > void intel_guc_slpc_fini(struct intel_guc_slpc *slpc) > { > + if (!slpc->vma) > + return; > + > + i915_vma_unpin_and_release(&slpc->vma, I915_VMA_RELEASE_MAP); > } > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > index 98036459a1a3..a2643b904165 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > @@ -3,12 +3,32 @@ > * > * Copyright © 2020 Intel Corporation > */ > + should be fixed in earlier patch > #ifndef _INTEL_GUC_SLPC_H_ > #define _INTEL_GUC_SLPC_H_ > > +#include > #include "intel_guc_slpc_fwif.h" > > struct intel_guc_slpc { > + /*Protects access to vma and SLPC actions */ hmm, missing mutex ;) > + struct i915_vma *vma; > + void *vaddr; no need to be void, define it as ptr to slpc_shared_data > + > + /* platform frequency limits */ > + u32 min_freq; > + u32 rp0_freq; > + u32 rp1_freq; > + > + /* frequency softlimits */ > + u32 min_freq_softlimit; > + u32 max_freq_softlimit; > + > + struct { > + u32 param_id; > + u32 param_value; > + u32 param_override; > + } debug; can you add all these extra fields in patches which will need them? Michal > }; > > int intel_guc_slpc_init(struct intel_guc_slpc *slpc); >
Re: [Intel-gfx] [PATCH 07/16] drm/i915/guc/slpc: Enable slpc and add related H2G events
On 10.07.2021 03:20, Vinay Belgaumkar wrote: > Add methods for interacting with guc for enabling SLPC. Enable > SLPC after guc submission has been established. GuC load will s/guc/GuC > fail if SLPC cannot be successfully initialized. Add various > helper methods to set/unset the parameters for SLPC. They can > be set using h2g calls or directly setting bits in the shared /h2g/H2G > data structure. > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 221 ++ > .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 4 - > drivers/gpu/drm/i915/gt/uc/intel_uc.c | 10 + > 3 files changed, 231 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index 94e2f19951aa..e579408d1c19 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -18,6 +18,61 @@ static inline struct intel_guc *slpc_to_guc(struct > intel_guc_slpc *slpc) > return container_of(slpc, struct intel_guc, slpc); > } > > +static inline struct intel_gt *slpc_to_gt(struct intel_guc_slpc *slpc) > +{ > + return guc_to_gt(slpc_to_guc(slpc)); > +} > + > +static inline struct drm_i915_private *slpc_to_i915(struct intel_guc_slpc > *slpc) > +{ > + return (slpc_to_gt(slpc))->i915; > +} > + > +static void slpc_mem_set_param(struct slpc_shared_data *data, > + u32 id, u32 value) > +{ > + GEM_BUG_ON(id >= SLPC_MAX_OVERRIDE_PARAMETERS); > + /* When the flag bit is set, corresponding value will be read > + * and applied by slpc. fix format of multi-line comment s/slpc/SLPC > + */ > + data->override_params_set_bits[id >> 5] |= (1 << (id % 32)); use __set_bit instead > + data->override_params_values[id] = value; > +} > + > +static void slpc_mem_unset_param(struct slpc_shared_data *data, > + u32 id) > +{ > + GEM_BUG_ON(id >= SLPC_MAX_OVERRIDE_PARAMETERS); > + /* When the flag bit is unset, corresponding value will not be > + * read by slpc. > + */ > + data->override_params_set_bits[id >> 5] &= (~(1 << (id % 32))); same here > + data->override_params_values[id] = 0; > +} > + > +static void slpc_mem_task_control(struct slpc_shared_data *data, > + u64 val, u32 enable_id, u32 disable_id) hmm, u64 to pass simple tri-state flag ? > +{ > + /* Enabling a param involves setting the enable_id > + * to 1 and disable_id to 0. Setting it to default > + * will unset both enable and disable ids and let > + * slpc choose it's default values. fix format + s/slpc/SLPC > + */ > + if (val == SLPC_PARAM_TASK_DEFAULT) { > + /* set default */ > + slpc_mem_unset_param(data, enable_id); > + slpc_mem_unset_param(data, disable_id); > + } else if (val == SLPC_PARAM_TASK_ENABLED) { > + /* set enable */ > + slpc_mem_set_param(data, enable_id, 1); > + slpc_mem_set_param(data, disable_id, 0); > + } else if (val == SLPC_PARAM_TASK_DISABLED) { > + /* set disable */ > + slpc_mem_set_param(data, disable_id, 1); > + slpc_mem_set_param(data, enable_id, 0); > + } maybe instead of SLPC_PARAM_TASK_* flags (that btw were confusing me earlier) you can define 3x small helpers: static void slpc_mem_set_default(data, enable_id, disable_id); static void slpc_mem_set_enabled(data, enable_id, disable_id); static void slpc_mem_set_disabled(data, enable_id, disable_id); > +} > + > static int slpc_shared_data_init(struct intel_guc_slpc *slpc) > { > struct intel_guc *guc = slpc_to_guc(slpc); > @@ -34,6 +89,128 @@ static int slpc_shared_data_init(struct intel_guc_slpc > *slpc) > return err; > } > > +/* > + * Send SLPC event to guc > + * > + */ > +static int slpc_send(struct intel_guc_slpc *slpc, > + struct slpc_event_input *input, > + u32 in_len) > +{ > + struct intel_guc *guc = slpc_to_guc(slpc); > + u32 *action; > + > + action = (u32 *)input; > + action[0] = INTEL_GUC_ACTION_SLPC_REQUEST; why not just updating input->h2g_action_id ? > + > + return intel_guc_send(guc, action, in_len); > +} > + > +static bool slpc_running(struct intel_guc_slpc *slpc) > +{ > + struct slpc_shared_data *data; > + u32 slpc_global_state; > + > + GEM_BUG_ON(!slpc->vma); > + > + drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data)); do you really need to flush all 8K of shared data? it looks that you only need single u32 > + data = slpc->vaddr; > + > + slpc_global_state = data->global_state; > + > + return (data->global_state == SLPC_GLOBAL_STATE_RUNNING); > +} > + > +static int host2guc_slpc_query_task_state(struct intel_guc_slpc *slpc) > +{ > + struct
Re: [PATCH 08/16] drm/i915/guc/slpc: Add methods to set min/max frequency
On 10.07.2021 03:20, Vinay Belgaumkar wrote: > Add param set h2g helpers to set the min and max frequencies > for use by SLPC. > > Signed-off-by: Sundaresan Sujaritha > Signed-off-by: Vinay Belgaumkar > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 94 + > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 2 + > 2 files changed, 96 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index e579408d1c19..19cb26479942 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -106,6 +106,19 @@ static int slpc_send(struct intel_guc_slpc *slpc, > return intel_guc_send(guc, action, in_len); > } > > +static int host2guc_slpc_set_param(struct intel_guc_slpc *slpc, > +u32 id, u32 value) > +{ > + struct slpc_event_input data = {0}; > + > + data.header.value = SLPC_EVENT(SLPC_EVENT_PARAMETER_SET, 2); > + data.args[0] = id; > + data.args[1] = value; > + > + return slpc_send(slpc, &data, 4); as suggested before, use of explicit function like: static int guc_action_slpc_param(guc, u32 id, u32 value) { u32 request[] = { INTEL_GUC_ACTION_SLPC_REQUEST, SLPC_EVENT(SLPC_EVENT_PARAMETER_SET, 2), id, value, }; return intel_guc_send(guc, request, ARRAY_SIZE(request)); } will be simpler/cleaner > +} > + > + > static bool slpc_running(struct intel_guc_slpc *slpc) > { > struct slpc_shared_data *data; > @@ -134,6 +147,19 @@ static int host2guc_slpc_query_task_state(struct > intel_guc_slpc *slpc) > return slpc_send(slpc, &data, 4); > } > > +static int slpc_set_param(struct intel_guc_slpc *slpc, u32 id, u32 value) > +{ > + struct drm_i915_private *i915 = slpc_to_i915(slpc); > + GEM_BUG_ON(id >= SLPC_MAX_PARAM); > + > + if (host2guc_slpc_set_param(slpc, id, value)) { > + drm_err(&i915->drm, "Unable to set param %x", id); missing \n what about printing value to be set ? what about printing send error %pe ? > + return -EIO; > + } > + > + return 0; > +} > + > static int slpc_read_task_state(struct intel_guc_slpc *slpc) > { > return host2guc_slpc_query_task_state(slpc); > @@ -218,6 +244,74 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc) > return slpc_shared_data_init(slpc); > } > > +/** > + * intel_guc_slpc_max_freq_set() - Set max frequency limit for SLPC. > + * @slpc: pointer to intel_guc_slpc. > + * @val: encoded frequency what's the encoding ? > + * > + * This function will invoke GuC SLPC action to update the max frequency > + * limit for slice and unslice. > + * > + * Return: 0 on success, non-zero error code on failure. > + */ > +int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val) > +{ > + int ret; > + struct drm_i915_private *i915 = slpc_to_i915(slpc); > + intel_wakeref_t wakeref; > + > + wakeref = intel_runtime_pm_get(&i915->runtime_pm); use can use with_intel_runtime_pm(rpm, wakeref) > + > + ret = slpc_set_param(slpc, > +SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ, > +val); > + > + if (ret) { > + drm_err(&i915->drm, > + "Set max frequency unslice returned %d", ret); missing \n print error with %pe but slpc_set_param returns only -EIO ;( > + ret = -EIO; > + goto done; > + } > + > +done: > + intel_runtime_pm_put(&i915->runtime_pm, wakeref); > + return ret; > +} > + > +/** > + * intel_guc_slpc_min_freq_set() - Set min frequency limit for SLPC. > + * @slpc: pointer to intel_guc_slpc. > + * @val: encoded frequency > + * > + * This function will invoke GuC SLPC action to update the min frequency > + * limit. > + * > + * Return: 0 on success, non-zero error code on failure. > + */ > +int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val) > +{ > + int ret; > + struct intel_guc *guc = slpc_to_guc(slpc); > + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; > + intel_wakeref_t wakeref; > + > + wakeref = intel_runtime_pm_get(&i915->runtime_pm); > + > + ret = slpc_set_param(slpc, > +SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ, > +val); > + if (ret) { > + drm_err(&i915->drm, > + "Set min frequency for unslice returned %d", ret); as above Michal > + ret = -EIO; > + goto done; > + } > + > +done: > + intel_runtime_pm_put(&i915->runtime_pm, wakeref); > + return ret; > +} > + > /* > * intel_guc_slpc_enable() - Start SLPC > * @slpc: pointer to intel_guc_slpc. > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > index a2643b904165..a473e1ea7c10 100644 > --- a/drivers/gpu/drm/i915/gt/uc/
Re: [PATCH 09/16] drm/i915/guc/slpc: Add get max/min freq hooks
On 10.07.2021 03:20, Vinay Belgaumkar wrote: > Add helpers to read the min/max frequency being used > by SLPC. This is done by send a h2g command which forces s/h2g/H2G > SLPC to update the shared data struct which can then be > read. > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 58 + > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 2 + > 2 files changed, 60 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index 19cb26479942..98a283d31734 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -278,6 +278,35 @@ int intel_guc_slpc_set_max_freq(struct intel_guc_slpc > *slpc, u32 val) > return ret; > } > > +int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val) > +{ > + struct slpc_shared_data *data; > + intel_wakeref_t wakeref; > + struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915; > + int ret = 0; > + > + wakeref = intel_runtime_pm_get(&i915->runtime_pm); > + > + /* Force GuC to update task data */ > + if (slpc_read_task_state(slpc)) { > + DRM_ERROR("Unable to update task data"); use drm_err missing \n maybe this message could be moved to slpc_read_task_state ? > + ret = -EIO; > + goto done; > + } > + > + GEM_BUG_ON(!slpc->vma); > + > + drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data)); maybe this can also be part of slpc_read_task_state ? > + data = slpc->vaddr; > + > + *val = DIV_ROUND_CLOSEST(data->task_state_data.max_unslice_freq * > + GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER); > + > +done: > + intel_runtime_pm_put(&i915->runtime_pm, wakeref); > + return ret; > +} > + > /** > * intel_guc_slpc_min_freq_set() - Set min frequency limit for SLPC. > * @slpc: pointer to intel_guc_slpc. > @@ -312,6 +341,35 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc > *slpc, u32 val) > return ret; > } > > +int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val) missing kernel-doc (above intel_guc_slpc_min_freq_set has one) > +{ > + struct slpc_shared_data *data; > + intel_wakeref_t wakeref; > + struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915; > + int ret = 0; > + > + wakeref = intel_runtime_pm_get(&i915->runtime_pm); > + > + /* Force GuC to update task data */ > + if (slpc_read_task_state(slpc)) { > + DRM_ERROR("Unable to update task data"); see above > + ret = -EIO; > + goto done; > + } > + > + GEM_BUG_ON(!slpc->vma); > + > + drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data)); see above Michal > + data = slpc->vaddr; > + > + *val = DIV_ROUND_CLOSEST(data->task_state_data.min_unslice_freq * > + GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER); > + > +done: > + intel_runtime_pm_put(&i915->runtime_pm, wakeref); > + return ret; > +} > + > /* > * intel_guc_slpc_enable() - Start SLPC > * @slpc: pointer to intel_guc_slpc. > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > index a473e1ea7c10..2cb830cdacb5 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h > @@ -36,5 +36,7 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc); > void intel_guc_slpc_fini(struct intel_guc_slpc *slpc); > int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val); > int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val); > +int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val); > +int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val); > > #endif >
Re: [PATCH 10/16] drm/i915/guc/slpc: Add debugfs for slpc info
On 10.07.2021 03:20, Vinay Belgaumkar wrote: > This prints out relevant SLPC info from the SLPC shared structure. > > We will send a h2g message which forces SLPC to update the > shared data structure with latest information before reading it. > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Sundaresan Sujaritha > --- > .../gpu/drm/i915/gt/uc/intel_guc_debugfs.c| 16 ++ > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 53 +++ > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 3 ++ > 3 files changed, 72 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c > index 9a03ff56e654..bef749e54601 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c > @@ -12,6 +12,7 @@ > #include "gt/uc/intel_guc_ct.h" > #include "gt/uc/intel_guc_ads.h" > #include "gt/uc/intel_guc_submission.h" > +#include "gt/uc/intel_guc_slpc.h" > > static int guc_info_show(struct seq_file *m, void *data) > { > @@ -50,11 +51,26 @@ static int guc_registered_contexts_show(struct seq_file > *m, void *data) > } > DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_registered_contexts); > > +static int guc_slpc_info_show(struct seq_file *m, void *unused) > +{ > + struct intel_guc *guc = m->private; > + struct intel_guc_slpc *slpc = &guc->slpc; > + struct drm_printer p = drm_seq_file_printer(m); > + > + if (!intel_guc_slpc_is_used(guc)) > + return -ENODEV; > + > + return intel_guc_slpc_info(slpc, &p); > +} > + other entries don't have empty line here > +DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_slpc_info); > + > void intel_guc_debugfs_register(struct intel_guc *guc, struct dentry *root) > { > static const struct debugfs_gt_file files[] = { > { "guc_info", &guc_info_fops, NULL }, > { "guc_registered_contexts", &guc_registered_contexts_fops, > NULL }, > + { "guc_slpc_info", &guc_slpc_info_fops, NULL}, IIRC last field is "eval" where maybe you could add your own to check if intel_guc_slpc_is_used() to avoid exposing this info if N/A > }; > > if (!intel_guc_is_supported(guc)) > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index 98a283d31734..d179ba14ece6 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -432,6 +432,59 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) > return 0; > } > > +int intel_guc_slpc_info(struct intel_guc_slpc *slpc, struct drm_printer *p) > +{ > + struct drm_i915_private *i915 = guc_to_gt(slpc_to_guc(slpc))->i915; > + struct slpc_shared_data *data; > + struct slpc_platform_info *platform_info; > + struct slpc_task_state_data *task_state_data; > + intel_wakeref_t wakeref; > + int ret = 0; > + > + wakeref = intel_runtime_pm_get(&i915->runtime_pm); > + > + if (slpc_read_task_state(slpc)) { > + ret = -EIO; > + goto done; > + } > + > + GEM_BUG_ON(!slpc->vma); > + > + drm_clflush_virt_range(slpc->vaddr, sizeof(struct slpc_shared_data)); likely will go away if integrated into slpc_read_task_state > + data = slpc->vaddr; > + > + platform_info = &data->platform_info; is this used ? > + task_state_data = &data->task_state_data; as it looks that you treat these sections separately, then maybe it would be cleaner to have: static void print_global_data(*global_data, *p) {} static void print_platform_info(*platform_info, *p) {} static void print_task_state_data(*task_state_data, *p) {} > + > + drm_printf(p, "SLPC state: %s\n", > slpc_state_stringify(data->global_state)); > + drm_printf(p, "\tgtperf task active: %d\n", > + task_state_data->gtperf_task_active); > + drm_printf(p, "\tdcc task active: %d\n", > + task_state_data->dcc_task_active); > + drm_printf(p, "\tin dcc: %d\n", > + task_state_data->in_dcc); > + drm_printf(p, "\tfreq switch active: %d\n", > + task_state_data->freq_switch_active); > + drm_printf(p, "\tibc enabled: %d\n", > + task_state_data->ibc_enabled); > + drm_printf(p, "\tibc active: %d\n", > + task_state_data->ibc_active); > + drm_printf(p, "\tpg1 enabled: %s\n", > + yesno(task_state_data->pg1_enabled)); > + drm_printf(p, "\tpg1 active: %s\n", > + yesno(task_state_data->pg1_active)); > + drm_printf(p, "\tmax freq: %dMHz\n", > + > DIV_ROUND_CLOSEST(data->task_state_data.max_unslice_freq * > + GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER)); > + drm_printf(p, "\tmin freq: %dMHz\n", > + > DIV_ROUND_CLOSEST(dat
Re: [Intel-gfx] [PATCH 12/16] drm/i915/guc/slpc: Cache platform frequency limits for slpc
On 10.07.2021 03:20, Vinay Belgaumkar wrote: > Cache rp0, rp1 and rpn platform limits into slpc structure > for range checking while setting min/max frequencies. > > Also add "soft" limits which keep track of frequency changes > made from userland. These are initially set to platform min > and max. > > Signed-off-by: Vinay Belgaumkar > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 41 + > 1 file changed, 41 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index d32274cd1db7..6e978f27b7a6 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -86,6 +86,9 @@ static int slpc_shared_data_init(struct intel_guc_slpc > *slpc) > return err; > } > > + slpc->max_freq_softlimit = 0; > + slpc->min_freq_softlimit = 0; as mentioned earlier, now it is time to introduce these fields in .h > + > return err; > } > > @@ -384,6 +387,29 @@ void intel_guc_pm_intrmsk_enable(struct intel_gt *gt) > GEN6_PMINTRMSK, pm_intrmsk_mbz, 0); > } > > +static int intel_guc_slpc_set_softlimits(struct intel_guc_slpc *slpc) > +{ > + int ret = 0; > + > + /* Softlimits are initially equivalent to platform limits > + * unless they have deviated from defaults, in which case, > + * we retain the values and set min/max accordingly. > + */ > + if (!slpc->max_freq_softlimit) > + slpc->max_freq_softlimit = slpc->rp0_freq; > + else if (slpc->max_freq_softlimit != slpc->rp0_freq) > + ret = intel_guc_slpc_set_max_freq(slpc, > + slpc->max_freq_softlimit); > + > + if (!slpc->min_freq_softlimit) > + slpc->min_freq_softlimit = slpc->min_freq; > + else if (slpc->min_freq_softlimit != slpc->min_freq) > + ret = intel_guc_slpc_set_min_freq(slpc, > + slpc->min_freq_softlimit); > + > + return ret; > +} > + > /* > * intel_guc_slpc_enable() - Start SLPC > * @slpc: pointer to intel_guc_slpc. > @@ -402,6 +428,7 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) > struct drm_i915_private *i915 = slpc_to_i915(slpc); > struct slpc_shared_data *data; > int ret; > + u32 rp_state_cap; move up to keep "ret" last > > GEM_BUG_ON(!slpc->vma); > > @@ -445,6 +472,20 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) > > DIV_ROUND_CLOSEST(data->task_state_data.max_unslice_freq * > GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER)); > > + rp_state_cap = intel_uncore_read(i915->gt.uncore, GEN6_RP_STATE_CAP); > + > + slpc->rp0_freq = ((rp_state_cap >> 0) & 0xff) * GT_FREQUENCY_MULTIPLIER; > + slpc->min_freq = ((rp_state_cap >> 16) & 0xff) * > GT_FREQUENCY_MULTIPLIER; > + slpc->rp1_freq = ((rp_state_cap >> 8) & 0xff) * GT_FREQUENCY_MULTIPLIER; we should have definitions for these bits and then we should be able to use REG_FIELD_GET > + > + if (intel_guc_slpc_set_softlimits(slpc)) > + drm_err(&i915->drm, "Unable to set softlimits"); missing \n maybe we can also print error ? > + > + drm_info(&i915->drm, > + "Platform fused frequency values - min: %u Mhz, max: %u Mhz", missing \n double space before 'min' Michal > + slpc->min_freq, > + slpc->rp0_freq); > + > return 0; > } > >
Re: [PATCH 14/16] drm/i915/guc/slpc: Sysfs hooks for slpc
On 10.07.2021 03:20, Vinay Belgaumkar wrote: > Update the get/set min/max freq hooks to work for > slpc case as well. Consolidate helpers for requested/min/max > frequency get/set to intel_rps where the proper action can > be taken depending on whether slpc is enabled. 2x s/slpc/SLPC > > Signed-off-by: Vinay Belgaumkar > Signed-off-by: Tvrtko Ursulin > Signed-off-by: Sujaritha Sundaresan > --- > drivers/gpu/drm/i915/gt/intel_rps.c | 135 > drivers/gpu/drm/i915/gt/intel_rps.h | 5 ++ > drivers/gpu/drm/i915/i915_pmu.c | 2 +- > drivers/gpu/drm/i915/i915_reg.h | 2 + > drivers/gpu/drm/i915/i915_sysfs.c | 71 +++ > 5 files changed, 154 insertions(+), 61 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c > b/drivers/gpu/drm/i915/gt/intel_rps.c > index e858eeb2c59d..88ffc5d90730 100644 > --- a/drivers/gpu/drm/i915/gt/intel_rps.c > +++ b/drivers/gpu/drm/i915/gt/intel_rps.c > @@ -37,6 +37,12 @@ static struct intel_uncore *rps_to_uncore(struct intel_rps > *rps) > return rps_to_gt(rps)->uncore; > } > > +static struct intel_guc_slpc *rps_to_slpc(struct intel_rps *rps) > +{ > + struct intel_gt *gt = rps_to_gt(rps); > + return >->uc.guc.slpc; either add empty line between decl/code or make it one-liner > +} > + > static bool rps_uses_slpc(struct intel_rps *rps) > { > struct intel_gt *gt = rps_to_gt(rps); > @@ -1960,6 +1966,135 @@ u32 intel_rps_read_actual_frequency(struct intel_rps > *rps) > return freq; > } > > +u32 intel_rps_read_punit_req(struct intel_rps *rps) > +{ > + struct intel_uncore *uncore = rps_to_uncore(rps); > + drop empty line > + u32 pureq = intel_uncore_read(uncore, GEN6_RPNSWREQ); > + > + return pureq; > +} > + > +u32 intel_rps_get_req(struct intel_rps *rps, u32 pureq) > +{ > + u32 req = pureq >> GEN9_SW_REQ_UNSLICE_RATIO_SHIFT; > + > + return req; > +} > + > +u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps) > +{ > + u32 freq = intel_rps_get_req(rps, intel_rps_read_punit_req(rps)); > + > + return intel_gpu_freq(rps, freq); > +} > + > +u32 intel_rps_get_requested_frequency(struct intel_rps *rps) > +{ > + if (rps_uses_slpc(rps)) > + return intel_rps_read_punit_req_frequency(rps); > + else > + return intel_gpu_freq(rps, rps->cur_freq); > +} > + > +u32 intel_rps_get_max_frequency(struct intel_rps *rps) > +{ > + struct intel_guc_slpc *slpc = rps_to_slpc(rps); > + > + if (rps_uses_slpc(rps)) > + return slpc->max_freq_softlimit; > + else > + return intel_gpu_freq(rps, rps->max_freq_softlimit); > +} > + > +int intel_rps_set_max_frequency(struct intel_rps *rps, u32 val) > +{ > + struct intel_guc_slpc *slpc = rps_to_slpc(rps); > + int ret; > + > + if (rps_uses_slpc(rps)) > + return intel_guc_slpc_set_max_freq(slpc, val); > + > + mutex_lock(&rps->lock); > + > + val = intel_freq_opcode(rps, val); > + if (val < rps->min_freq || > + val > rps->max_freq || > + val < rps->min_freq_softlimit) { > + ret = -EINVAL; > + goto unlock; > + } > + > + if (val > rps->rp0_freq) > + DRM_DEBUG("User requested overclocking to %d\n", use drm_dbg Michal > + intel_gpu_freq(rps, val)); > + > + rps->max_freq_softlimit = val; > + > + val = clamp_t(int, rps->cur_freq, > + rps->min_freq_softlimit, > + rps->max_freq_softlimit); > + > + /* > + * We still need *_set_rps to process the new max_delay and > + * update the interrupt limits and PMINTRMSK even though > + * frequency request may be unchanged. > + */ > + intel_rps_set(rps, val); > + > +unlock: > + mutex_unlock(&rps->lock); > + > + return ret; > +} > + > +u32 intel_rps_get_min_frequency(struct intel_rps *rps) > +{ > + struct intel_guc_slpc *slpc = rps_to_slpc(rps); > + > + if (rps_uses_slpc(rps)) > + return slpc->min_freq_softlimit; > + else > + return intel_gpu_freq(rps, rps->min_freq_softlimit); > +} > + > +int intel_rps_set_min_frequency(struct intel_rps *rps, u32 val) > +{ > + struct intel_guc_slpc *slpc = rps_to_slpc(rps); > + int ret; > + > + if (rps_uses_slpc(rps)) > + return intel_guc_slpc_set_min_freq(slpc, val); > + > + mutex_lock(&rps->lock); > + > + val = intel_freq_opcode(rps, val); > + if (val < rps->min_freq || > + val > rps->max_freq || > + val > rps->max_freq_softlimit) { > + ret = -EINVAL; > + goto unlock; > + } > + > + rps->min_freq_softlimit = val; > + > + val = clamp_t(int, rps->cur_freq, > + rps->min_freq_softlimit, > + rps->max_freq_softlimit); > + > + /* > + * We still need *_set_rps to process the new min_delay and > + * update the interrupt limits and PMINTRMSK
Re: [PATCH 15/16] drm/i915/guc/slpc: slpc selftest
On 10.07.2021 03:20, Vinay Belgaumkar wrote: > Tests that exercise the slpc get/set frequency interfaces. > > Clamp_max will set max frequency to multiple levels and check > that slpc requests frequency lower than or equal to it. > > Clamp_min will set min frequency to different levels and check > if slpc requests are higher or equal to those levels. 2x s/slpc/SLPC > > Signed-off-by: Vinay Belgaumkar > --- > drivers/gpu/drm/i915/gt/intel_rps.c | 1 + > drivers/gpu/drm/i915/gt/selftest_slpc.c | 333 ++ > drivers/gpu/drm/i915/gt/selftest_slpc.h | 12 + > .../drm/i915/selftests/i915_live_selftests.h | 1 + > 4 files changed, 347 insertions(+) > create mode 100644 drivers/gpu/drm/i915/gt/selftest_slpc.c > create mode 100644 drivers/gpu/drm/i915/gt/selftest_slpc.h > > diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c > b/drivers/gpu/drm/i915/gt/intel_rps.c > index 88ffc5d90730..16ac2e840881 100644 > --- a/drivers/gpu/drm/i915/gt/intel_rps.c > +++ b/drivers/gpu/drm/i915/gt/intel_rps.c > @@ -2288,4 +2288,5 @@ EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable); > > #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) > #include "selftest_rps.c" > +#include "selftest_slpc.c" > #endif > diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c > b/drivers/gpu/drm/i915/gt/selftest_slpc.c > new file mode 100644 > index ..f440c1cb2afa > --- /dev/null > +++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c > @@ -0,0 +1,333 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright © 2020 Intel Corporation 2021 > + */ > +#include "selftest_slpc.h" > +#include "selftest_rps.h" > + > +#include > +#include system headers should go first > + > +#include "intel_engine_heartbeat.h" > +#include "intel_engine_pm.h" > +#include "intel_gpu_commands.h" > +#include "intel_gt_clock_utils.h" > +#include "intel_gt_pm.h" > +#include "intel_rc6.h" > +#include "selftest_engine_heartbeat.h" > +#include "intel_rps.h" > +#include "selftests/igt_flush_test.h" > +#include "selftests/igt_spinner.h" wrong order ? > + > +#define NUM_STEPS 5 > +#define H2G_DELAY 5 > +#define delay_for_h2g() usleep_range(H2G_DELAY, H2G_DELAY + 1) > + > +static int set_min_freq(struct intel_guc_slpc *slpc, int freq) > +{ > + int ret; add empty line > + ret = intel_guc_slpc_set_min_freq(slpc, freq); > + if (ret) { > + pr_err("Could not set min frequency to [%d]\n", freq); > + return ret; > + } else { > + /* Delay to ensure h2g completes */ > + delay_for_h2g(); > + } > + > + return ret; > +} > + > +static int set_max_freq(struct intel_guc_slpc *slpc, int freq) > +{ > + int ret; add empty line > + ret = intel_guc_slpc_set_max_freq(slpc, freq); > + if (ret) { > + pr_err("Could not set maximum frequency [%d]\n", > + freq); > + return ret; > + } else { > + /* Delay to ensure h2g completes */ > + delay_for_h2g(); > + } > + > + return ret; > +} > + > +int live_slpc_clamp_min(void *arg) > +{ > + struct drm_i915_private *i915 = arg; > + struct intel_gt *gt = &i915->gt; > + struct intel_guc_slpc *slpc; > + struct intel_rps *rps; > + struct intel_engine_cs *engine; > + enum intel_engine_id id; > + struct igt_spinner spin; > + int err = 0; usually "err" is last decl > + u32 slpc_min_freq, slpc_max_freq; > + > + too many empty lines > + slpc = >->uc.guc.slpc; > + rps = >->rps; could be initialized in decl above > + > + if (!intel_uc_uses_guc_slpc(>->uc)) > + return 0; > + > + if (igt_spinner_init(&spin, gt)) > + return -ENOMEM; > + > + if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) { > + pr_err("Could not get SLPC max freq"); > + return -EIO; > + } > + > + if (intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq)) { > + pr_err("Could not get SLPC min freq"); > + return -EIO; > + } > + > + if (slpc_min_freq == slpc_max_freq) { > + pr_err("Min/Max are fused to the same value"); > + return -EINVAL; > + } 3x missing \n > + > + intel_gt_pm_wait_for_idle(gt); > + intel_gt_pm_get(gt); > + for_each_engine(engine, gt, id) { > + struct i915_request *rq; > + u32 step, min_freq, req_freq; > + u32 act_freq, max_act_freq; > + > + if (!intel_engine_can_store_dword(engine)) > + continue; > + > + /* Go from min to max in 5 steps */ > + step = (slpc_max_freq - slpc_min_freq)/NUM_STEPS; add spaces ") / NUM" > + max_act_freq = slpc_min_freq; > + for (min_freq = slpc_min_freq; min_freq < slpc_max_freq; > min_freq+=step) add spaces " += " > + { > + err = set_min_freq(slpc, min_freq); > + if (err) > +
Re: [Intel-gfx] [PATCH 16/16] drm/i915/guc/rc: Setup and enable GUCRC feature
On 10.07.2021 03:20, Vinay Belgaumkar wrote: > This feature hands over the control of HW RC6 to the GUC. > GUC decides when to put HW into RC6 based on it's internal > busyness algorithms. > > GUCRC needs GUC submission to be enabled, and only > supported on Gen12+ for now. > > When GUCRC is enabled, do not set HW RC6. Use a H2G message > to tell guc to enable GUCRC. When disabling RC6, tell guc to s/GUC/GuC s/guc/GuC > revert RC6 control back to KMD. > > Signed-off-by: Vinay Belgaumkar > --- > drivers/gpu/drm/i915/Makefile | 1 + > drivers/gpu/drm/i915/gt/intel_rc6.c | 22 -- > .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 6 ++ > drivers/gpu/drm/i915/gt/uc/intel_guc.c| 1 + > drivers/gpu/drm/i915/gt/uc/intel_guc.h| 2 + > drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c | 79 +++ > drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h | 32 > drivers/gpu/drm/i915/gt/uc/intel_uc.h | 2 + > 8 files changed, 140 insertions(+), 5 deletions(-) > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h > > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile > index d8eac4468df9..3fc17f20d88e 100644 > --- a/drivers/gpu/drm/i915/Makefile > +++ b/drivers/gpu/drm/i915/Makefile > @@ -186,6 +186,7 @@ i915-y += gt/uc/intel_uc.o \ > gt/uc/intel_guc_fw.o \ > gt/uc/intel_guc_log.o \ > gt/uc/intel_guc_log_debugfs.o \ > + gt/uc/intel_guc_rc.o \ > gt/uc/intel_guc_slpc.o \ > gt/uc/intel_guc_submission.o \ > gt/uc/intel_huc.o \ > diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c > b/drivers/gpu/drm/i915/gt/intel_rc6.c > index 259d7eb4e165..299fcf10b04b 100644 > --- a/drivers/gpu/drm/i915/gt/intel_rc6.c > +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c > @@ -98,11 +98,19 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6) > set(uncore, GEN9_MEDIA_PG_IDLE_HYSTERESIS, 60); > set(uncore, GEN9_RENDER_PG_IDLE_HYSTERESIS, 60); > > - /* 3a: Enable RC6 */ > - rc6->ctl_enable = > - GEN6_RC_CTL_HW_ENABLE | > - GEN6_RC_CTL_RC6_ENABLE | > - GEN6_RC_CTL_EI_MODE(1); > + /* 3a: Enable RC6 > + * > + * With GUCRC, we do not enable bit 31 of RC_CTL, > + * thus allowing GuC to control RC6 entry/exit fully instead. > + * We will not set the HW ENABLE and EI bits > + */ > + if (!intel_guc_rc_enable(>->uc.guc)) > + rc6->ctl_enable = GEN6_RC_CTL_RC6_ENABLE; > + else > + rc6->ctl_enable = > + GEN6_RC_CTL_HW_ENABLE | > + GEN6_RC_CTL_RC6_ENABLE | > + GEN6_RC_CTL_EI_MODE(1); > > pg_enable = > GEN9_RENDER_PG_ENABLE | > @@ -513,6 +521,10 @@ static void __intel_rc6_disable(struct intel_rc6 *rc6) > { > struct drm_i915_private *i915 = rc6_to_i915(rc6); > struct intel_uncore *uncore = rc6_to_uncore(rc6); > + struct intel_gt *gt = rc6_to_gt(rc6); > + > + /* Take control of RC6 back from GuC */ > + intel_guc_rc_disable(>->uc.guc); > > intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); > if (GRAPHICS_VER(i915) >= 9) > diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > index 596cf4b818e5..2ddb9cdc0a59 100644 > --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > @@ -136,6 +136,7 @@ enum intel_guc_action { > INTEL_GUC_ACTION_CONTEXT_RESET_NOTIFICATION = 0x1008, > INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION = 0x1009, > INTEL_GUC_ACTION_SLPC_REQUEST = 0x3003, > + INTEL_GUC_ACTION_SETUP_PC_GUCRC = 0x3004, > INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000, > INTEL_GUC_ACTION_REGISTER_CONTEXT = 0x4502, > INTEL_GUC_ACTION_DEREGISTER_CONTEXT = 0x4503, > @@ -146,6 +147,11 @@ enum intel_guc_action { > INTEL_GUC_ACTION_LIMIT > }; > > +enum intel_guc_rc_options { > + INTEL_GUCRC_HOST_CONTROL, > + INTEL_GUCRC_FIRMWARE_CONTROL, > +}; > + > enum intel_guc_preempt_options { > INTEL_GUC_PREEMPT_OPTION_DROP_WORK_Q = 0x4, > INTEL_GUC_PREEMPT_OPTION_DROP_SUBMIT_Q = 0x8, > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > index 82863a9bc8e8..0d55b24f7c67 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > @@ -158,6 +158,7 @@ void intel_guc_init_early(struct intel_guc *guc) > intel_guc_log_init_early(&guc->log); > intel_guc_submission_init_early(guc); > intel_guc_slpc_init_early(guc); > + intel_guc_rc_init_early(guc); > > mutex_init(&guc->send_mutex); > spin_lock_init(&guc->irq_lock); > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > index 0dbbd9cf553f
Re: [PATCH 23/47] drm/i915/guc: Update GuC debugfs to support new GuC
On 24.06.2021 09:04, Matthew Brost wrote: > Update GuC debugfs to support the new GuC structures. > > Signed-off-by: John Harrison > Signed-off-by: Matthew Brost > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 22 > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h | 3 ++ > .../gpu/drm/i915/gt/uc/intel_guc_debugfs.c| 23 +++- > .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 52 +++ > .../gpu/drm/i915/gt/uc/intel_guc_submission.h | 4 ++ > drivers/gpu/drm/i915/i915_debugfs.c | 1 + > 6 files changed, 104 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > index e0f92e28350c..4ed074df88e5 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > @@ -1135,3 +1135,25 @@ void intel_guc_ct_event_handler(struct intel_guc_ct > *ct) > > ct_try_receive_message(ct); > } > + > +void intel_guc_log_ct_info(struct intel_guc_ct *ct, this is not "guc log" function, it is "guc ct" one, so: void intel_guc_ct_print_info(struct intel_guc_ct *ct, > +struct drm_printer *p) > +{ > + if (!ct->enabled) { > + drm_puts(p, "CT disabled\n"); nit: maybe drm_puts(p, "CT %s\n", enableddisabled(false)); > + return; > + } > + > + drm_printf(p, "H2G Space: %u\n", > +atomic_read(&ct->ctbs.send.space) * 4); don't you want to print size ? or GGTT offset ? > + drm_printf(p, "Head: %u\n", > +ct->ctbs.send.desc->head); > + drm_printf(p, "Tail: %u\n", > +ct->ctbs.send.desc->tail); > + drm_printf(p, "G2H Space: %u\n", > +atomic_read(&ct->ctbs.recv.space) * 4); > + drm_printf(p, "Head: %u\n", > +ct->ctbs.recv.desc->head); > + drm_printf(p, "Tail: %u\n", > +ct->ctbs.recv.desc->tail); hmm, what about adding helper: static void dump_ctb(struct intel_guc_ct_buffer *ctb, *p) { drm_printf(p, "Size: %u\n", ctb->size); drm_printf(p, "Space: %u\n", atomic_read(&ctb->space) * 4); drm_printf(p, "Head: %u\n", ctb->desc->head); drm_printf(p, "Tail: %u\n", ctb->desc->tail); } and then: drm_printf(p, "H2G:\n"); dump_ctb(&ct->ctbs.send, p); drm_printf(p, "G2H:\n"); dump_ctb(&ct->ctbs.recv, p); or dump_ctb(&ct->ctbs.send, "H2G", p); dump_ctb(&ct->ctbs.recv, "G2H", p); > +} > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h > index ab1b79ab960b..f62eb06b32fc 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h > @@ -16,6 +16,7 @@ > > struct i915_vma; > struct intel_guc; > +struct drm_printer; > > /** > * DOC: Command Transport (CT). > @@ -106,4 +107,6 @@ int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 > *action, u32 len, > u32 *response_buf, u32 response_buf_size, u32 flags); > void intel_guc_ct_event_handler(struct intel_guc_ct *ct); > > +void intel_guc_log_ct_info(struct intel_guc_ct *ct, struct drm_printer *p); > + > #endif /* _INTEL_GUC_CT_H_ */ > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c > index fe7cb7b29a1e..62b9ce0fafaa 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c > @@ -9,6 +9,8 @@ > #include "intel_guc.h" > #include "intel_guc_debugfs.h" > #include "intel_guc_log_debugfs.h" > +#include "gt/uc/intel_guc_ct.h" > +#include "gt/uc/intel_guc_submission.h" > > static int guc_info_show(struct seq_file *m, void *data) > { > @@ -22,16 +24,35 @@ static int guc_info_show(struct seq_file *m, void *data) > drm_puts(&p, "\n"); > intel_guc_log_info(&guc->log, &p); > > - /* Add more as required ... */ > + if (!intel_guc_submission_is_used(guc)) > + return 0; > + > + intel_guc_log_ct_info(&guc->ct, &p); > + intel_guc_log_submission_info(guc, &p); > > return 0; > } > DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_info); > > +static int guc_registered_contexts_show(struct seq_file *m, void *data) > +{ > + struct intel_guc *guc = m->private; > + struct drm_printer p = drm_seq_file_printer(m); > + > + if (!intel_guc_submission_is_used(guc)) > + return -ENODEV; > + > + intel_guc_log_context_info(guc, &p); > + > + return 0; > +} > +DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_registered_contexts); > + > void intel_guc_debugfs_register(struct intel_guc *guc, struct dentry *root) > { > static const struct debugfs_gt_file files[] = { > { "guc_info", &guc_info_fops, NULL }, > + { "guc_registered_contexts", &guc_registered_contexts_fops, > NULL }, > }; > > if (!intel_guc_is_supported(guc)) > diff --git
Re: [PATCH v7 3/7] drm/i915: Prepare for multiple GTs
On 19.03.2022 00:39, Andi Shyti wrote: > From: Tvrtko Ursulin > > 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 > Signed-off-by: Daniele Ceraolo Spurio > Signed-off-by: Tvrtko Ursulin > Signed-off-by: Matt Roper > Signed-off-by: Andi Shyti > Cc: Daniele Ceraolo Spurio > Cc: Joonas Lahtinen > Cc: Matthew Auld > Reviewed-by: Matt Roper > Reviewed-by: Andrzej Hajda > --- > drivers/gpu/drm/i915/gt/intel_gt.c| 133 -- > drivers/gpu/drm/i915/gt/intel_gt.h| 17 ++- > 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| 28 ++-- > drivers/gpu/drm/i915/i915_drv.h | 6 + > drivers/gpu/drm/i915/intel_memory_region.h| 3 + > drivers/gpu/drm/i915/intel_uncore.c | 11 +- > drivers/gpu/drm/i915/intel_uncore.h | 3 +- > .../gpu/drm/i915/selftests/mock_gem_device.c | 13 +- > 10 files changed, 184 insertions(+), 46 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c > b/drivers/gpu/drm/i915/gt/intel_gt.c > index ca875ba3e2a9d..cfac4a913642e 100644 > --- a/drivers/gpu/drm/i915/gt/intel_gt.c > +++ b/drivers/gpu/drm/i915/gt/intel_gt.c > @@ -29,7 +29,7 @@ > #include "intel_uncore.h" > #include "shmem_utils.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(>->irq_lock); > > @@ -51,17 +51,23 @@ void __intel_gt_init_early(struct intel_gt *gt, struct > drm_i915_private *i915) > intel_rps_init_early(>->rps); > } > > -void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915) > +/* Preliminary initialization of Tile 0 */ > +void intel_root_gt_init_early(struct drm_i915_private *i915) > { > + struct intel_gt *gt = to_gt(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; > + int id = INTEL_REGION_LMEM_0 + instance; > struct intel_memory_region *mem; > - int id; > int err; > > mem = intel_gt_setup_lmem(gt); > @@ -76,9 +82,8 @@ int intel_gt_probe_lmem(struct intel_gt *gt) > return err; > } > > - id = INTEL_REGION_LMEM_0; > - > mem->id = id; > + mem->instance = instance; > > intel_memory_region_set_name(mem, "local%u", mem->instance); > > @@ -807,16 +812,21 @@ void intel_gt_driver_release(struct intel_gt *gt) > intel_gt_fini_hwconfig(gt); > } > > -void intel_gt_driver_late_release(struct intel_gt *gt) > +void intel_gt_driver_late_release_all(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(>->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(>->uc); > + intel_gt_fini_requests(gt); > + intel_gt_fini_reset(gt); > + intel_gt_fini_timelines(gt); > + intel_engines_free(gt); > + } > } > > /** > @@ -1013,6 +1023,105 @@ void intel_gt_report_steering(struct drm_printer *p, > struct intel_gt *gt, > } > } > > +static int intel_gt_tile_setup(struct intel_gt *gt, phys_addr_t phys_addr) > +{ > + int ret; > + > + if (!gt_is_root(gt)) { > + struct intel_uncore_mmio_debug *mmio_debug; > + struct intel_uncore *uncore; > + > + uncore = kzalloc(sizeof(*uncore), GFP_KERNEL); > + if (!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_i
Re: [PATCH v2 4/7] drm/i915/guc: use the memcpy_from_wc call from the drm
On 21.03.2022 22:14, Lucas De Marchi wrote: > On Thu, Mar 03, 2022 at 11:30:10PM +0530, Balasubramani Vivekanandan wrote: >> memcpy_from_wc functions in i915_memcpy.c will be removed and replaced >> by the implementation in drm_cache.c. >> Updated to use the functions provided by drm_cache.c. >> >> v2: Check if the log object allocated from local memory or system memory >> and according setup the iosys_map (Lucas) >> >> Cc: Lucas De Marchi >> >> Signed-off-by: Balasubramani Vivekanandan >> >> --- >> drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 15 --- >> 1 file changed, 12 insertions(+), 3 deletions(-) >> >> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c >> b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c >> index a24dc6441872..b9db765627ea 100644 >> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c >> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c >> @@ -3,6 +3,7 @@ >> * Copyright © 2014-2019 Intel Corporation >> */ >> >> +#include >> #include >> #include >> >> @@ -206,6 +207,7 @@ static void guc_read_update_log_buffer(struct >> intel_guc_log *log) >> enum guc_log_buffer_type type; >> void *src_data, *dst_data; >> bool new_overflow; >> + struct iosys_map src_map; >> >> mutex_lock(&log->relay.lock); >> >> @@ -282,14 +284,21 @@ static void guc_read_update_log_buffer(struct >> intel_guc_log *log) >> } >> >> /* Just copy the newly written data */ >> + if (i915_gem_object_is_lmem(log->vma->obj)) >> + iosys_map_set_vaddr_iomem(&src_map, (void __iomem >> *)src_data); >> + else >> + iosys_map_set_vaddr(&src_map, src_data); > > It would be better to keep this outside of the loop. So inside the loop > we can use only iosys_map_incr(&src_map, buffer_size). However you'd > also have to handle the read_offset. The iosys_map_ API has both a > src_offset and dst_offset due to situations like that. Maybe this is > missing in the new drm_memcpy_* function you're adding? > > This function was not correct wrt to IO memory access with the other > 2 places in this function doing plain memcpy(). Since we are starting to > use iosys_map here, we probably should handle this commit as "migrate to > iosys_map", and convert those. In your current final state > we have 3 variables aliasing the same memory location. IMO it will be > error prone to keep it like that > > +Michal, some questions: @Lucas, better to ask Alan who is making some changes around GuC log @Alan, can you help answer below questions? thanks, Michal > > - I'm not very familiar with the relayfs API. Is the `dst_data += > PAGE_SIZE;` > really correct? > > - Could you double check this patch and ack if ok? > > Heads up that since the log buffer is potentially in lmem, we will need > to convert this function to take that into account. All those accesses > to log_buf_state need to use the proper kernel abstraction for system vs > I/O memory. > > thanks > Lucas De Marchi > >> + >> if (read_offset > write_offset) { >> - i915_memcpy_from_wc(dst_data, src_data, write_offset); >> + drm_memcpy_from_wc_vaddr(dst_data, &src_map, >> + write_offset); >> bytes_to_copy = buffer_size - read_offset; >> } else { >> bytes_to_copy = write_offset - read_offset; >> } >> - i915_memcpy_from_wc(dst_data + read_offset, >> - src_data + read_offset, bytes_to_copy); >> + iosys_map_incr(&src_map, read_offset); >> + drm_memcpy_from_wc_vaddr(dst_data + read_offset, &src_map, >> + bytes_to_copy); >> >> src_data += buffer_size; >> dst_data += buffer_size; >> -- >> 2.25.1 >>
Re: [PATCH v5 1/4] drm/i915/guc: Add fetch of hwconfig table
On 22.02.2022 11:36, Jordan Justen wrote: > From: John Harrison > > Implement support for fetching the hardware description table from the > GuC. The call is made twice - once without a destination buffer to > query the size and then a second time to fill in the buffer. > > Note that the table is only available on ADL-P and later platforms. > > v5 (of Jordan's posting): > * Various changes made by Jordan and recommended by Michal >- Makefile ordering >- Adjust "struct intel_guc_hwconfig hwconfig" comment >- Set Copyright year to 2022 in intel_guc_hwconfig.c/.h >- Drop inline from hwconfig_to_guc() >- Replace hwconfig param with guc in __guc_action_get_hwconfig() >- Move zero size check into guc_hwconfig_discover_size() >- Change comment to say zero size offset/size is needed to get size >- Add has_guc_hwconfig to devinfo and drop has_table() >- Change drm_err to notice in __uc_init_hw() and use %pe > > Cc: Michal Wajdeczko > Signed-off-by: Rodrigo Vivi > Signed-off-by: John Harrison > Reviewed-by: Matthew Brost > Acked-by: Jon Bloomfield > Signed-off-by: Jordan Justen > --- > drivers/gpu/drm/i915/Makefile | 1 + > .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 1 + > .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 4 + > drivers/gpu/drm/i915/gt/uc/intel_guc.h| 3 + > .../gpu/drm/i915/gt/uc/intel_guc_hwconfig.c | 145 ++ > .../gpu/drm/i915/gt/uc/intel_guc_hwconfig.h | 19 +++ > drivers/gpu/drm/i915/gt/uc/intel_uc.c | 7 + > drivers/gpu/drm/i915/i915_pci.c | 1 + > drivers/gpu/drm/i915/intel_device_info.h | 1 + > 9 files changed, 182 insertions(+) > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.h > > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile > index e9ce09620eb5..661f1afb51d7 100644 > --- a/drivers/gpu/drm/i915/Makefile > +++ b/drivers/gpu/drm/i915/Makefile > @@ -188,6 +188,7 @@ i915-y += gt/uc/intel_uc.o \ > gt/uc/intel_guc_ct.o \ > gt/uc/intel_guc_debugfs.o \ > gt/uc/intel_guc_fw.o \ > + gt/uc/intel_guc_hwconfig.o \ > gt/uc/intel_guc_log.o \ > gt/uc/intel_guc_log_debugfs.o \ > gt/uc/intel_guc_rc.o \ > diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > index fe5d7d261797..4a61c819f32b 100644 > --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > @@ -137,6 +137,7 @@ enum intel_guc_action { > INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION = 0x1009, > INTEL_GUC_ACTION_SETUP_PC_GUCRC = 0x3004, > INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000, > + INTEL_GUC_ACTION_GET_HWCONFIG = 0x4100, > INTEL_GUC_ACTION_REGISTER_CONTEXT = 0x4502, > INTEL_GUC_ACTION_DEREGISTER_CONTEXT = 0x4503, > INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER = 0x4505, > diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h > b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h > index 488b6061ee89..f9e2a6aaef4a 100644 > --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h > +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h > @@ -8,6 +8,10 @@ > > enum intel_guc_response_status { > INTEL_GUC_RESPONSE_STATUS_SUCCESS = 0x0, > + INTEL_GUC_RESPONSE_NOT_SUPPORTED = 0x20, > + INTEL_GUC_RESPONSE_NO_ATTRIBUTE_TABLE = 0x201, > + INTEL_GUC_RESPONSE_NO_DECRYPTION_KEY = 0x202, > + INTEL_GUC_RESPONSE_DECRYPTION_FAILED = 0x204, > INTEL_GUC_RESPONSE_STATUS_GENERIC_FAIL = 0xF000, > }; > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > index f9240d4baa69..2058eb8c3d0c 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > @@ -13,6 +13,7 @@ > #include "intel_guc_fw.h" > #include "intel_guc_fwif.h" > #include "intel_guc_ct.h" > +#include "intel_guc_hwconfig.h" > #include "intel_guc_log.h" > #include "intel_guc_reg.h" > #include "intel_guc_slpc_types.h" > @@ -37,6 +38,8 @@ struct intel_guc { > struct intel_guc_ct ct; > /** @slpc: sub-structure containing SLPC related data and objects */ > struct intel_guc_slpc slpc; > + /** @hwconfig: data related to hardware configuration KLV blob */ > + struct intel_guc_hwconfig hwconfig; > > /** @sched_engine: Global engine used to submit requests to GuC */ > struct i915_sched_en
Re: [PATCH v5 1/4] drm/i915/guc: Add fetch of hwconfig table
On 25.02.2022 06:03, Jordan Justen wrote: > John Harrison writes: > >> On 2/22/2022 02:36, Jordan Justen wrote: >>> From: John Harrison >>> >>> Implement support for fetching the hardware description table from the >>> GuC. The call is made twice - once without a destination buffer to >>> query the size and then a second time to fill in the buffer. >>> >>> Note that the table is only available on ADL-P and later platforms. >>> >>> v5 (of Jordan's posting): >>> * Various changes made by Jordan and recommended by Michal >>> - Makefile ordering >>> - Adjust "struct intel_guc_hwconfig hwconfig" comment >>> - Set Copyright year to 2022 in intel_guc_hwconfig.c/.h >>> - Drop inline from hwconfig_to_guc() >>> - Replace hwconfig param with guc in __guc_action_get_hwconfig() >>> - Move zero size check into guc_hwconfig_discover_size() >>> - Change comment to say zero size offset/size is needed to get size >>> - Add has_guc_hwconfig to devinfo and drop has_table() >>> - Change drm_err to notice in __uc_init_hw() and use %pe >>> >>> Cc: Michal Wajdeczko >>> Signed-off-by: Rodrigo Vivi >>> Signed-off-by: John Harrison >>> Reviewed-by: Matthew Brost >>> Acked-by: Jon Bloomfield >>> Signed-off-by: Jordan Justen >>> --- >>> >>> + ret = intel_guc_hwconfig_init(&guc->hwconfig); >>> + if (ret) >>> + drm_notice(&i915->drm, "Failed to retrieve hwconfig table: >>> %pe\n", >> Why only drm_notice? As you are keen to point out, the UMDs won't work >> if the table is not available. All the failure paths in your own >> verification function are 'drm_err'. So why is it only a 'notice' if >> there is no table at all? > > This was requested by Michal in my v3 posting: > > https://patchwork.freedesktop.org/patch/472936/?series=99787&rev=3 > > I don't think that it should be a failure for i915 if it is unable to > read the table, or if the table read is invalid. I think it should be up > to the UMD to react to the missing hwconfig however they think is > appropriate, but I would like the i915 to guarantee & document the > format returned to userspace to whatever extent is feasible. > > As you point out there is a discrepancy, and I think I should be > consistent with whatever is used here in my "drm/i915/guc: Verify > hwconfig blob matches supported format" patch. > > I guess I'd tend to agree with Michal that "maybe drm_notice since we > continue probe", but I would go along with either if you two want to > discuss further. having consistent message level is a clear benefit but on other hand these other 'errors' may indicate more serious problems related to use of wrong/incompatible firmware that returns corrupted HWconfig (or we use wrong actions), while since we are not using this HWconfig in the driver we don't care that much that we failed to load HWconfig and 'notice' is enough. but I'm fine with all messages being drm_err (as we will not have to change that once again after HWconfig will be mandatory for the driver as well) > >> Note that this function is called as part of the reset path. The reset >> path is not allowed to allocate memory. The table is stored in a >> dynamically allocated object. Hence the IGT test failure. The table >> query has to be done elsewhere at driver init time only. > > Thanks for clearing this up. I did notice on dg2 that gpu resets were > causing a re-read of the hwconfig from GuC, but it definitely was not > clear to me that there would be a connection to the IGT failure that you > pointed out. > >> >>> + ERR_PTR(ret)); >>> + >>> ret = guc_enable_communication(guc); >>> if (ret) >>> goto err_log_capture; >>> @@ -562,6 +567,8 @@ static void __uc_fini_hw(struct intel_uc *uc) >>> if (intel_uc_uses_guc_submission(uc)) >>> intel_guc_submission_disable(guc); >>> >>> + intel_guc_hwconfig_fini(&guc->hwconfig); >>> + >>> __uc_sanitize(uc); >>> } >>> >>> diff --git a/drivers/gpu/drm/i915/i915_pci.c >>> b/drivers/gpu/drm/i915/i915_pci.c >>> index 76e590fcb903..1d31e35a5154 100644 >>> --- a/drivers/gpu/drm/i915/i915_pci.c >>> +++ b/drivers/gpu/drm/i915/i915_pci.c >>> @@ -990,6 +990,7 @@ static const struct intel_device_
Re: [Intel-gfx] [PATCH v5 1/4] drm/i915/guc: Add fetch of hwconfig table
On 25.02.2022 18:18, Tvrtko Ursulin wrote: > > On 25/02/2022 16:46, John Harrison wrote: > driver we don't care that much that we failed to load HWconfig and 'notice' is enough. but I'm fine with all messages being drm_err (as we will not have to change that once again after HWconfig will be mandatory for the driver as well) >>> >>> I would be against drm_err. >>> >>> #define KERN_EMERG KERN_SOH "0" /* system is unusable */ >>> #define KERN_ALERT KERN_SOH "1" /* action must be taken >>> immediately */ >>> #define KERN_CRIT KERN_SOH "2" /* critical conditions */ >>> #define KERN_ERR KERN_SOH "3" /* error conditions */ >>> #define KERN_WARNING KERN_SOH "4" /* warning conditions */ >>> #define KERN_NOTICE KERN_SOH "5" /* normal but significant >>> condition */ >>> #define KERN_INFO KERN_SOH "6" /* informational */ >>> #define KERN_DEBUG KERN_SOH "7" /* debug-level messages */ >>> >>> From the point of view of the kernel driver, this is not an error to >>> its operation. It can at most be a warning, but notice is also fine >>> by me. One could argue when reading "normal but significant >>> condition" that it is not normal, when it is in fact unexpected, so >>> if people prefer warning that is also okay by me. I still lean >>> towards notice becuase of the hands-off nature i915 has with the >>> pass-through of this blob. >> From the point of view of the KMD, i915 will load and be 'functional' >> if it can't talk to the hardware at all. The UMDs won't work at all but > > Well this reductio ad absurdum fails I think... :) > >> the driver load will be 'fine'. That's a requirement to be able to get >> the user to a software fallback desktop in order to work out why the >> hardware isn't working (e.g. no GuC firmware file). I would view this >> as similar. The KMD might have loaded but the UMDs are not functional. >> That is definitely an error condition to me. > > ... If GuC fails to load there is no command submission and driver will > obviously log that with drm_err. > > If blob fails to verify it depends on the userspace stack what will > happen. As stated before on some platforms, and/or after a certain time, > Mesa will not look at the blob at all. So i915 is fine (it is after all > just a conduit for opaque data!), system overall is fine, so it > definitely isn't a KERN_ERR level event. > >>> + ERR_PTR(ret)); >>> + >>> ret = guc_enable_communication(guc); >>> if (ret) >>> goto err_log_capture; >>> @@ -562,6 +567,8 @@ static void __uc_fini_hw(struct intel_uc *uc) >>> if (intel_uc_uses_guc_submission(uc)) >>> intel_guc_submission_disable(guc); >>> + intel_guc_hwconfig_fini(&guc->hwconfig); >>> + >>> __uc_sanitize(uc); >>> } >>> diff --git a/drivers/gpu/drm/i915/i915_pci.c >>> b/drivers/gpu/drm/i915/i915_pci.c >>> index 76e590fcb903..1d31e35a5154 100644 >>> --- a/drivers/gpu/drm/i915/i915_pci.c >>> +++ b/drivers/gpu/drm/i915/i915_pci.c >>> @@ -990,6 +990,7 @@ static const struct intel_device_info >>> adl_p_info = { >>> BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | >>> BIT(VCS2), >>> .ppgtt_size = 48, >>> .dma_mask_size = 39, >>> + .has_guc_hwconfig = 1, >> Who requested this change? It was previously done this way but the >> instruction was that i915_pci.c is for hardware features only but >> that >> this, as you seem extremely keen about pointing out at every >> opportunity, is a software feature. > > This was requested by Michal as well. I definitely agree it is a > software feature, but I was not aware that "i915_pci.c is for hardware > features only". > > Michal, do you agree with this and returning to the previous method > for > enabling the feature? now I'm little confused as some arch direction was to treat FW as extension of the HW so for me it was natural to have 'has_guc_hwconfig' flag in device_info if still for some reason it is undesired to mix HW and FW/SW flags inside single group of flags then maybe we should just add separate group of immutable flags where has_guc_hwconfig could be defined. let our maintainers decide >>> >>> Bah.. :) >>> >>> And what was the previous method? >>> >>> [comes back later] >>> >>> Okay it was: >>> >>> +static bool has_table(struct drm_i915_private *i915) >>> +{ >>> + if (IS_ALDERLAKE_P(i915)) >>> + return true; >>> >>> Which sucks a bit if we want to argue it does not belong in device info. >>> >>> Why can't we ask the GuC if the blob exists? In fact what would >>> happen if one would call __guc_action_get_hwconfig on any GuC platform? >> That was how I originally wrote the code. However, other parties >> refuse to allow a H2G call to fail. The underlyi
Re: [PATCH v5 1/7] drm/i915: Rename INTEL_REGION_LMEM with INTEL_REGION_LMEM_0
On 17.02.2022 15:41, Andi Shyti wrote: > With the upcoming multitile support each tile will have its own > local memory. Mark the current LMEM with the suffix '0' to > emphasise that it belongs to the root tile. > > Suggested-by: Michal Wajdeczko > Signed-off-by: Andi Shyti > --- > drivers/gpu/drm/i915/display/intel_fb.c | 2 +- > drivers/gpu/drm/i915/display/intel_fb_pin.c | 2 +- > drivers/gpu/drm/i915/gem/i915_gem_lmem.c | 4 ++-- > drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c | 6 +++--- > drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c | 8 > drivers/gpu/drm/i915/gt/intel_gt.c| 2 +- > drivers/gpu/drm/i915/intel_memory_region.c| 2 +- > drivers/gpu/drm/i915/intel_memory_region.h| 4 ++-- > 8 files changed, 15 insertions(+), 15 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_fb.c > b/drivers/gpu/drm/i915/display/intel_fb.c > index 23cfe2e5ce2a..421f7238da05 100644 > --- a/drivers/gpu/drm/i915/display/intel_fb.c > +++ b/drivers/gpu/drm/i915/display/intel_fb.c > @@ -1981,7 +1981,7 @@ intel_user_framebuffer_create(struct drm_device *dev, > > /* object is backed with LMEM for discrete */ > i915 = to_i915(obj->base.dev); > - if (HAS_LMEM(i915) && !i915_gem_object_can_migrate(obj, > INTEL_REGION_LMEM)) { > + if (HAS_LMEM(i915) && !i915_gem_object_can_migrate(obj, > INTEL_REGION_LMEM_0)) { > /* object is "remote", not in local memory */ > i915_gem_object_put(obj); > return ERR_PTR(-EREMOTE); > diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.c > b/drivers/gpu/drm/i915/display/intel_fb_pin.c > index a307b4993bcf..bd6e7c98e751 100644 > --- a/drivers/gpu/drm/i915/display/intel_fb_pin.c > +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.c > @@ -140,7 +140,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, > if (!ret && phys_cursor) > ret = i915_gem_object_attach_phys(obj, alignment); > else if (!ret && HAS_LMEM(dev_priv)) > - ret = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM); > + ret = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM_0); > /* TODO: Do we need to sync when migration becomes async? */ > if (!ret) > ret = i915_gem_object_pin_pages(obj); > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c > b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c > index 444f8268b9c5..47e43dc3a174 100644 > --- a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c > +++ b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c > @@ -100,7 +100,7 @@ __i915_gem_object_create_lmem_with_ps(struct > drm_i915_private *i915, > resource_size_t page_size, > unsigned int flags) > { > - return > i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_LMEM], > + return > i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_LMEM_0], >size, page_size, flags); > } > > @@ -135,6 +135,6 @@ i915_gem_object_create_lmem(struct drm_i915_private *i915, > resource_size_t size, > unsigned int flags) > { > - return > i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_LMEM], > + return > i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_LMEM_0], >size, 0, flags); > } > diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c > b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c > index b071a58dd6da..a342fd387d4e 100644 > --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c > +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c > @@ -88,7 +88,7 @@ static int igt_dmabuf_import_self(void *arg) > static int igt_dmabuf_import_same_driver_lmem(void *arg) > { > struct drm_i915_private *i915 = arg; > - struct intel_memory_region *lmem = i915->mm.regions[INTEL_REGION_LMEM]; > + struct intel_memory_region *lmem = > i915->mm.regions[INTEL_REGION_LMEM_0]; > struct drm_i915_gem_object *obj; > struct drm_gem_object *import; > struct dma_buf *dmabuf; > @@ -252,10 +252,10 @@ static int igt_dmabuf_import_same_driver_lmem_smem(void > *arg) > struct drm_i915_private *i915 = arg; > struct intel_memory_region *regions[2]; > > - if (!i915->mm.regions[INTEL_REGION_LMEM]) > + if (!i915->mm.regions[INTEL_REGION_LMEM_0]) > return 0; > > - regions[0] = i915->
Re: [Intel-gfx] [PATCH v5 3/7] drm/i915/gt: add gt_is_root() helper
On 17.02.2022 15:41, Andi Shyti wrote: > The "gt_is_root(struct intel_gt *gt)" helper return true if the > gt is the root gt, which means that its id is 0. Return false > otherwise. > > Suggested-by: Michal Wajdeczko > Signed-off-by: Andi Shyti > --- > drivers/gpu/drm/i915/gt/intel_gt.h | 5 + > 1 file changed, 5 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h > b/drivers/gpu/drm/i915/gt/intel_gt.h > index 915d6192079b..f17f51e2d394 100644 > --- a/drivers/gpu/drm/i915/gt/intel_gt.h > +++ b/drivers/gpu/drm/i915/gt/intel_gt.h > @@ -19,6 +19,11 @@ struct drm_printer; > ##__VA_ARGS__); \ > } while (0) > > +static inline bool gt_is_root(struct intel_gt *gt) > +{ > + return !gt->info.id; > +} > + we could squash this patch with prev one, where it can be used in: intel_gt_tile_cleanup(struct intel_gt *gt) { intel_uncore_cleanup_mmio(gt->uncore); - if (gt->info.id) { + if (!gt_is_root(gt)) { kfree(gt->uncore); kfree(gt); } } or just use it this way in this patch, with that: Reviewed-by: Michal Wajdeczko > static inline struct intel_gt *uc_to_gt(struct intel_uc *uc) > { > return container_of(uc, struct intel_gt, uc);
Re: [PATCH v5 7/7] drm/i915/gt: Adding new sysfs frequency attributes
On 17.02.2022 15:41, Andi Shyti wrote: > From: Sujaritha Sundaresan > > This patch adds the following new sysfs frequency attributes; > - punit_req_freq_mhz > - throttle_reason_status > - throttle_reason_pl1 > - throttle_reason_pl2 > - throttle_reason_pl4 > - throttle_reason_thermal > - throttle_reason_prochot > - throttle_reason_ratl > - throttle_reason_vr_thermalert > - throttle_reason_vr_tdc > > Signed-off-by: Sujaritha Sundaresan > Signed-off-by: Andi Shyti > Cc: Dale B Stimson > --- > drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c | 142 > drivers/gpu/drm/i915/gt/intel_rps.c | 83 > drivers/gpu/drm/i915/gt/intel_rps.h | 10 ++ > drivers/gpu/drm/i915/i915_reg.h | 11 ++ > 4 files changed, 246 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c > b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c > index 8e86b8f675f1..8be676cd1607 100644 > --- a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c > +++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c > @@ -463,6 +463,141 @@ static ssize_t rps_rp_mhz_show(struct device *dev, > static const struct attribute * const gen6_rps_attrs[] = GEN6_RPS_ATTR; > static const struct attribute * const gen6_gt_attrs[] = GEN6_GT_ATTR; > > +static ssize_t punit_req_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 = >->rps; > + u32 preq = intel_rps_read_punit_req_frequency(rps); > + > + return scnprintf(buff, PAGE_SIZE, "%d\n", preq); %u since preq is u32 and use sysfs_emit (also in below show functions) > +} > + > +static ssize_t throttle_reason_status_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 = >->rps; > + bool status = !!intel_rps_read_throttle_reason_status(rps); > + > + return scnprintf(buff, PAGE_SIZE, "%u\n", status); > +} > + > +static ssize_t throttle_reason_pl1_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 = >->rps; > + bool pl1 = !!intel_rps_read_throttle_reason_pl1(rps); > + > + return scnprintf(buff, PAGE_SIZE, "%u\n", pl1); > +} > + > +static ssize_t throttle_reason_pl2_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 = >->rps; > + bool pl2 = !!intel_rps_read_throttle_reason_pl2(rps); > + > + return scnprintf(buff, PAGE_SIZE, "%u\n", pl2); > +} > + > +static ssize_t throttle_reason_pl4_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 = >->rps; > + bool pl4 = !!intel_rps_read_throttle_reason_pl4(rps); > + > + return scnprintf(buff, PAGE_SIZE, "%u\n", pl4); > +} > + > +static ssize_t throttle_reason_thermal_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 = >->rps; > + bool thermal = !!intel_rps_read_throttle_reason_thermal(rps); > + > + return scnprintf(buff, PAGE_SIZE, "%u\n", thermal); > +} > + > +static ssize_t throttle_reason_prochot_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 = >->rps; > + bool prochot = !!intel_rps_read_throttle_reason_prochot(rps); > + > + return scnprintf(buff, PAGE_SIZE, "%u\n", prochot); > +} > + > +static ssize_t throttle_reason_ratl_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 = >->rps; > + bool ratl = !!intel_rps_read_throttle_reason_ratl(rps); > + > + return scnprintf(buff, PAGE_SIZE, "%u\n",
Re: [PATCH 4/4] drm/i915/guc: Inject probe errors for CT send
On 11.10.2021 20:00, Matthew Brost wrote: > On Mon, Oct 11, 2021 at 08:51:06PM +0530, Thanneeru Srinivasulu wrote: >> Inject probe errors -ENXIO, -EBUSY for CT send. >> >> Signed-off-by: Thanneeru Srinivasulu >> --- >> drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 8 >> 1 file changed, 8 insertions(+) >> >> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> index 83764db0fd6d..8ffef3abd3da 100644 >> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> @@ -765,6 +765,14 @@ int intel_guc_ct_send(struct intel_guc_ct *ct, const >> u32 *action, u32 len, >> u32 status = ~0; /* undefined */ >> int ret; >> >> +ret = i915_inject_probe_error(ct_to_i915(ct), -ENXIO); >> +if (ret) >> +return ret; >> + > > I don't see where -ENXIO is returned during an error that we handle > unless I am missing something. If we don't return -ENXIO anywhere else I > don't think we need to inject this error. but the point of this exercise is not to handle such error but to gracefully abort probe without panic or leaks. note that we are already using -ENXIO in many other injected failure points (mostly in uc code) thus for me above change is also fine and the whole series is: Reviewed-by: Michal Wajdeczko -Michal > > Matt > >> +ret = i915_inject_probe_error(ct_to_i915(ct), -EBUSY); >> +if (ret) >> +return ret; >> + >> if (unlikely(!ct->enabled)) { >> struct intel_guc *guc = ct_to_guc(ct); >> struct intel_uc *uc = container_of(guc, struct intel_uc, guc); >> -- >> 2.25.1 >>
Re: [Intel-gfx] [PATCH 1/4] drm/i915/huc: Use i915_probe_error to report early CTB failures
On 12.10.2021 18:16, Jani Nikula wrote: > On Mon, 11 Oct 2021, Matthew Brost wrote: >> On Mon, Oct 11, 2021 at 08:51:03PM +0530, Thanneeru Srinivasulu wrote: >>> Replace DRM_ERROR with CT_PROBE_ERROR to report early CTB failures. >>> >>> Signed-off-by: Thanneeru Srinivasulu >> >> Reviewed-by: Matthew Brost >> >>> --- >>> drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 4 ++-- >>> 1 file changed, 2 insertions(+), 2 deletions(-) >>> >>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >>> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >>> index 0a3504bc0b61..83764db0fd6d 100644 >>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >>> @@ -191,8 +191,8 @@ static int ct_register_buffer(struct intel_guc_ct *ct, >>> u32 type, >>> err = guc_action_register_ct_buffer(ct_to_guc(ct), type, >>> desc_addr, buff_addr, size); >>> if (unlikely(err)) >>> - CT_ERROR(ct, "Failed to register %s buffer (%pe)\n", >>> -guc_ct_buffer_type_to_str(type), ERR_PTR(err)); >>> + CT_PROBE_ERROR(ct, "Failed to register %s buffer (%pe)\n", >>> + guc_ct_buffer_type_to_str(type), ERR_PTR(err)); > > Please tell me why we are adding not just i915-specific logging helpers, > but file specific ones? > > To be honest I'd like to see all of the CT_ERROR, CT_DEBUG, > CT_PROBE_ERROR macros just gone. the reason for CT_DEBUG is that it can be quite noisy so we must have an easy option to compile it out on non-debug configs, can't just replace that helper with drm_dbg or i915_dbg (that we don't have) as it will be available likely on I915_DEBUG config, while we want more fine control. use of file (or component) level helpers allows us to simplify the code (no need to repeat long i915->drm lookup from component pointer) and we may provide common prefix and/or classification of the messages. extra bonus, especially useful after introduction of multi-gt support, will be possibility of augmenting message to include gt identifier, without the need to update all existing places if they were using i915- or drm- level functions directly. for this last feature, likely "gt" specific intel_gt_err|probe_err|dbg helpers will do the job as well, so if someone introduce them, I'm happy to convert CT_ERROR calls to these new helpers if really really needed. -Michal > > > BR, > Jani. > > >>> return err; >>> } >>> >>> -- >>> 2.25.1 >>> >
[PATCH] drm/i915: Use fixed offset for PTEs location
We assumed that for all modern GENs the PTEs and register space are split in the GTTMMADR BAR, but while it is true, we should rather use fixed offset as it is defined in the specification. Bspec: 4409, 4457, 4604, 11181, 9027, 13246, 13321, 44980 Signed-off-by: Michal Wajdeczko Cc: CQ Tang Cc: Matt Roper --- drivers/gpu/drm/i915/gt/intel_ggtt.c | 19 +-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index ba7c7ed89fa8..f17383e76eb7 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -813,6 +813,21 @@ static unsigned int chv_get_total_gtt_size(u16 gmch_ctrl) return 0; } +static unsigned int gen6_gttmmadr_size(struct drm_i915_private *i915) +{ + /* +* GEN6: GTTMMADR size is 4MB and GTTADR starts at 2MB offset +* GEN8: GTTMMADR size is 16MB and GTTADR starts at 8MB offset +*/ + GEM_BUG_ON(GRAPHICS_VER(i915) < 6); + return (GRAPHICS_VER(i915) < 8) ? SZ_4M : SZ_16M; +} + +static unsigned int gen6_gttadr_offset(struct drm_i915_private *i915) +{ + return gen6_gttmmadr_size(i915) / 2; +} + static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) { struct drm_i915_private *i915 = ggtt->vm.i915; @@ -821,8 +836,8 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) u32 pte_flags; int ret; - /* For Modern GENs the PTEs and register space are split in the BAR */ - phys_addr = pci_resource_start(pdev, 0) + pci_resource_len(pdev, 0) / 2; + GEM_WARN_ON(pci_resource_len(pdev, 0) != gen6_gttmmadr_size(i915)); + phys_addr = pci_resource_start(pdev, 0) + gen6_gttadr_offset(i915); /* * On BXT+/ICL+ writes larger than 64 bit to the GTT pagetable range -- 2.25.1
Re: [PATCH v4 1/2] drm/i915: Prepare for multiple GTs
Hi Andi, please find few late nits below On 17.01.2022 20:32, Andi Shyti wrote: > From: Tvrtko Ursulin > > 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 s/gts/GTs (to match as below) > 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 > Signed-off-by: Daniele Ceraolo Spurio > Signed-off-by: Tvrtko Ursulin > Signed-off-by: Matt Roper > Signed-off-by: Andi Shyti > Cc: Daniele Ceraolo Spurio > Cc: Joonas Lahtinen > Cc: Matthew Auld > Reviewed-by: Matt Roper > --- > 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) no need to split line > { > spin_lock_init(>->irq_lock); > > @@ -47,19 +48,27 @@ void __intel_gt_init_early(struct intel_gt *gt, struct > drm_i915_private *i915) > intel_rps_init_early(>->rps); > } > > +/* Preliminary initialization of Tile 0 */ maybe: void intel_gts_init_early(struct drm_i915_private *i915) { struct intel_gt *gt = &i915->gt0; ... > 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) as breaks naming style maybe there should be different helper like: void intel_gts_driver_late_release(struct drm_i915_private *i915) { struct intel_gt *gt; unsigned int id; for_each_gt(gt, i915, id) intel_gt_driver_late_release(gt); } then we can use "intel_gts" prefix to indicate that we want to operate on all GTs, not just single "intel_gt" > { > + 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(>->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(>->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
Re: [PATCH v4 2/2] drm/i915/gt: make a gt sysfs group and move power management files
Hi Andi, few more late nits below On 17.01.2022 20:32, 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. A > warning will be issued if the old interfaces will be accessed. > > 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 gtN ? > │ ├── 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 > Signed-off-by: Lucas De Marchi > Cc: Matt Roper > Cc: Sujaritha Sundaresan > Cc: Tvrtko Ursulin > Reviewed-by: Sujaritha Sundaresan > --- > drivers/gpu/drm/i915/Makefile | 4 +- > drivers/gpu/drm/i915/gt/intel_gt.c| 2 + > drivers/gpu/drm/i915/gt/sysfs_gt.c| 136 + > drivers/gpu/drm/i915/gt/sysfs_gt.h| 32 +++ > drivers/gpu/drm/i915/gt/sysfs_gt_pm.c | 392 ++ > drivers/gpu/drm/i915/gt/sysfs_gt_pm.h | 16 ++ > drivers/gpu/drm/i915/i915_drv.h | 2 + > drivers/gpu/drm/i915/i915_sysfs.c | 315 + > drivers/gpu/drm/i915/i915_sysfs.h | 3 + > 9 files changed, 596 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 shouldn't these be named as > + gt/intel_gt_sysfs.o \ > + gt/intel_gt_pm_sysfs.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(>->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 ..7a2f1d91f221 > --- /dev/null > +++ b/drivers/gpu/drm/i915/gt/sysfs_gt.c > @@ -0,0 +1,136 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright © 2020 Intel Corporation 2022 ? > + */ > + > +#include > +#include > +#include > +#include > +#include > + > +#include "i915_drv.h" > +#include "i915_sysfs.h" > +#include "intel_gt.h" > +#include "intel_gt_
Re: [Intel-gfx] [PATCH v4 2/2] drm/i915: Use to_root_gt() to refer to the root tile
On 01.12.2021 01:38, Lucas De Marchi wrote: > On Wed, Dec 01, 2021 at 12:41:08AM +0200, Andi Shyti wrote: >> Hi Lucas, >> >> fist of all thanks for taking a look at this, I was eagerly >> waiting for reviewers. >> >> On Tue, Nov 30, 2021 at 01:07:30PM -0800, Lucas De Marchi wrote: >>> On Sun, Nov 28, 2021 at 01:09:26PM +0200, Andi Shyti wrote: >>> > Starting from a patch from Matt to_root_gt() returns the >>> > reference to the root tile in order to abstract the root tile >>> > from th callers. >>> > >>> > Being the root tile identified as tile '0', embed the id in the >>> > name so that i915->gt becomes i915->gt0. >>> > >>> > The renaming has been mostly done with the following command and >>> > some manual fixes. >>> > >>> > sed -i -e sed -i 's/\&i915\->gt\./\&to_root_gt(i915)\->/g' \ >>> > -e sed -i 's/\&dev_priv\->gt\./\&to_root_gt(dev_priv)\->/g' \ >>> > -e 's/\&dev_priv\->gt/to_root_gt(dev_priv)/g' \ >>> > -e 's/\&i915\->gt/to_root_gt(i915)/g' \ >>> > -e 's/dev_priv\->gt\./to_root_gt(dev_priv)\->/g' \ >>> > -e 's/i915\->gt\./to_root_gt(i915)\->/g' \ >>> > `find drivers/gpu/drm/i915/ -name *.[ch]` >>> > >>> > Two small changes have been added to this commit: >>> > >>> > 1. intel_reset_gpu() in intel_display.c retreives the gt from >>> > to_scanout_gt() >>> > 2. in set_scheduler_caps() the gt is taken from the engine and >>> > not from i915. >>> >>> Ideally the non-automatic changes should be in separate patches, before >>> the ones that can be done by automation. Because then it becomes easier >>> to apply the final result without conflicts. >> >> OK >> >>> This is quite a big diff to merge in one go. Looking at the pending >>> patches from Michal however I see he had similar changes, split in >>> sensible chunks.. Could you split your version like that? at least >>> gt/gem and display would be good to have separate. Or sync with Michal >>> on how to proceed with these versions Here are his patches: >>> >>> drm/i915: Remove i915->ggtt >>> drm/i915: Use to_gt() helper for GGTT accesses >>> drm/i915: Use to_gt() helper >>> drm/i915/gvt: Use to_gt() helper >>> drm/i915/gem: Use to_gt() helper >>> drm/i915/gt: Use to_gt() helper >>> drm/i915/display: Use to_gt() helper >>> drm/i915: Introduce to_gt() helper >> >> I understand... will follow this approach. >> >>> This first patch also removed the `struct intel_gt *gt = to_gt(pool)`, >>> that would otherwise be a leftover in >>> drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c >> >> One difference from Michal patch is that I am not using the >> wrapper >> >> to_gt(...) >> >> but >> >> to_root_gt(...) >> >> which was introduced by Matt. To me sounds more meaningful as it >> specifies that we are really looking for the root tile and not >> any tile. > > yes, I think it makes sense, too. Michal, any comment? I think you > also had other plans to get the root gt by another helper... ? The main rationale to use generic "to_gt()" helper name in all existing i915->gt cases in (other) Michal patches was that on some upcoming configs we want to distinguish between "primary" and "root" tile and use "to_root_gt()" helper only when referring to the root tile as described in Bspec:52416. Note that since current code baseline is still "single" tile, you can't tell whether all of these functions really expects special "root" tile or just "any" tile. Thus to avoid confusion or mistakes I would suggest to keep simple name "to_gt()" as in most cases usages of this helper it will likely be replaced with iterator from for_each_gt loop and any remaining usages will just mean "primary" tile or replaced with explicit "to_root_gt()" if really needed. Michal
Re: [PATCH 4/5] drm/i915/guc: Update to GuC version 69.0.0
On 03.12.2021 19:33, john.c.harri...@intel.com wrote: > From: John Harrison > > Update to the latest GuC release. > > The latest GuC firmware introduces a number of interface changes: Why can't we review all these changes in smaller patches and squash them in separate CI series *after* collecting all required r-b ? Michal > > GuC may return NO_RESPONSE_RETRY message for requests sent over CTB. > Add support for this reply and try resending the request again as a > new CTB message. > > A KLV (key-length-value) mechanism is now used for passing > configuration data such as CTB management. > > With the new KLV scheme, the old CTB management actions are no longer > used and are removed. > > Register capture on hang is now supported by GuC. Full i915 support > for this will be added by a later patch. A minimum support of > providing capture memory and register lists is required though, so add > that in. > > The device id of the current platform needs to be provided at init time. > > The 'poll CS' w/a (Wa_22012773006) was blanket enabled by previous > versions of GuC. It must now be explicitly requested by the KMD. So, > add in the code to turn it on when relevant. > > The GuC log entry format has changed. This requires adding a new field > to the log header structure to mark the wrap point at the end of the > buffer (as the buffer size is no longer a multiple of the log entry > size). > > New CTB notification messages are now sent for some things that were > previously only sent via MMIO notifications. > > Of these, the crash dump notification was not really being handled by > i915. It called the log flush code but that only flushed the regular > debug log and then only if relay logging was enabled. So just report > an error message instead. > > The 'exception' notification was just being ignored completely. So add > an error message for that as well. > > Note that in either the crash dump or the exception case, the GuC is > basically dead. The KMD will detect this via the heartbeat and trigger > both an error log (which will include the crash dump as part of the > GuC log) and a GT reset. So no other processing is really required. > > Signed-off-by: John Harrison > Signed-off-by: Michal Wajdeczko > --- > Documentation/gpu/i915.rst| 1 + > .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 80 +- > drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h | 82 ++ > drivers/gpu/drm/i915/gt/uc/intel_guc.c| 126 +--- > drivers/gpu/drm/i915/gt/uc/intel_guc.h| 4 + > drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 45 +- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 141 ++ > drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 37 - > drivers/gpu/drm/i915/gt/uc/intel_guc_log.c| 31 ++-- > drivers/gpu/drm/i915/gt/uc/intel_guc_log.h| 3 + > .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 18 +++ > drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 30 ++-- > 12 files changed, 434 insertions(+), 164 deletions(-) > create mode 100644 drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h > > diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst > index b7d801993bfa..bcaefc952764 100644 > --- a/Documentation/gpu/i915.rst > +++ b/Documentation/gpu/i915.rst > @@ -539,6 +539,7 @@ GuC ABI > .. kernel-doc:: drivers/gpu/drm/i915/gt/uc/abi/guc_communication_mmio_abi.h > .. kernel-doc:: drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h > .. kernel-doc:: drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > +.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h > > HuC > --- > diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > index fe5d7d261797..7afdadc7656f 100644 > --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > @@ -7,9 +7,9 @@ > #define _ABI_GUC_ACTIONS_ABI_H > > /** > - * DOC: HOST2GUC_REGISTER_CTB > + * DOC: HOST2GUC_SELF_CFG > * > - * This message is used as part of the `CTB based communication`_ setup. > + * This message is used by Host KMD to setup of the `GuC Self Config KLVs`_. > * > * This message must be sent as `MMIO HXG Message`_. > * > @@ -22,20 +22,18 @@ > * | > +---+--+ > * | | 27:16 | DATA0 = MBZ > | > * | > +---+--+ > - * | | 15:0 | ACTION = _`GUC_ACTION_HOST2GUC_REGISTER_CTB` = 0x4505 &g
Re: [PATCH] drm/i915: Flip guc_id allocation partition
On 11.01.2022 17:30, Matthew Brost wrote: > Move the multi-lrc guc_id from the lower allocation partition (0 to > number of multi-lrc guc_ids) to upper allocation partition (number of > single-lrc to max guc_ids). > > Signed-off-by: Matthew Brost > --- > .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 57 ++- > 1 file changed, 42 insertions(+), 15 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > index 9989d121127df..1bacc9621cea8 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > @@ -147,6 +147,8 @@ guc_create_parallel(struct intel_engine_cs **engines, > */ > #define NUMBER_MULTI_LRC_GUC_ID(guc) \ > ((guc)->submission_state.num_guc_ids / 16) > +#define NUMBER_SINGLE_LRC_GUC_ID(guc)\ > + ((guc)->submission_state.num_guc_ids - NUMBER_MULTI_LRC_GUC_ID(guc)) above two will likely look better if converted into inline functions, or even better if we explicitly store slrc/mlrc upper/lower id limits under guc submission state > > /* > * Below is a set of functions which control the GuC scheduling state which > @@ -1776,11 +1778,6 @@ int intel_guc_submission_init(struct intel_guc *guc) > INIT_WORK(&guc->submission_state.destroyed_worker, > destroyed_worker_func); > > - guc->submission_state.guc_ids_bitmap = > - bitmap_zalloc(NUMBER_MULTI_LRC_GUC_ID(guc), GFP_KERNEL); > - if (!guc->submission_state.guc_ids_bitmap) > - return -ENOMEM; > - > spin_lock_init(&guc->timestamp.lock); > INIT_DELAYED_WORK(&guc->timestamp.work, guc_timestamp_ping); > guc->timestamp.ping_delay = (POLL_TIME_CLKS / gt->clock_frequency + 1) > * HZ; > @@ -1796,7 +1793,8 @@ void intel_guc_submission_fini(struct intel_guc *guc) > guc_flush_destroyed_contexts(guc); > guc_lrc_desc_pool_destroy(guc); > i915_sched_engine_put(guc->sched_engine); > - bitmap_free(guc->submission_state.guc_ids_bitmap); > + if (guc->submission_state.guc_ids_bitmap) > + bitmap_free(guc->submission_state.guc_ids_bitmap); it should be fine to pass NULL to bitmap_free, no? > } > > static inline void queue_request(struct i915_sched_engine *sched_engine, > @@ -1863,6 +1861,33 @@ static void guc_submit_request(struct i915_request *rq) > spin_unlock_irqrestore(&sched_engine->lock, flags); > } > > +static int new_mlrc_guc_id(struct intel_guc *guc, struct intel_context *ce) > +{ > + int ret; > + > + GEM_BUG_ON(!intel_context_is_parent(ce)); > + GEM_BUG_ON(!guc->submission_state.guc_ids_bitmap); > + > + ret = bitmap_find_free_region(guc->submission_state.guc_ids_bitmap, > +NUMBER_MULTI_LRC_GUC_ID(guc), > +order_base_2(ce->parallel.number_children > + + 1)); btw, is there any requirement (GuC ABI ?) that allocated ids need to be allocated with power of 2 alignment ? I don't think that we must optimize that hard and in some cases waste extra ids (as we might be limited on some configs) > + if (likely(!(ret < 0))) > + ret += NUMBER_SINGLE_LRC_GUC_ID(guc); nit: more readable would be if (unlikely(ret < 0)) return ret; return ret + guc->submission_state.mlrc_base; > + > + return ret; > +} > + > +static int new_slrc_guc_id(struct intel_guc *guc, struct intel_context *ce) > +{ > + GEM_BUG_ON(intel_context_is_parent(ce)); do we really need ce here ? > + > + return ida_simple_get(&guc->submission_state.guc_ids, > + 0, NUMBER_SINGLE_LRC_GUC_ID(guc), if we change the logic of NUMBER_SINGLE/MULTI_LRC_GUC_ID macros from static split into more dynamic, then we could likely implement lazy increase of available slrc/mlrc id limits on demand, within available range, without deciding upfront of the hardcoded split 15 : 1 but this can be done next time ;) > + GFP_KERNEL | __GFP_RETRY_MAYFAIL | > + __GFP_NOWARN); > +} > + > static int new_guc_id(struct intel_guc *guc, struct intel_context *ce) > { > int ret; > @@ -1870,16 +1895,10 @@ static int new_guc_id(struct intel_guc *guc, struct > intel_context *ce) > GEM_BUG_ON(intel_context_is_child(ce)); > > if (intel_context_is_parent(ce)) > - ret = > bitmap_find_free_region(guc->submission_state.guc_ids_bitmap, > - NUMBER_MULTI_LRC_GUC_ID(guc), > - > order_base_2(ce->parallel.number_children > -+ 1)); > + ret = new_mlrc_guc_id(guc, ce); > else > - ret = ida_simple_get(&guc->submission_state.guc_ids, > - NUMBER_
Re: [PATCH] drm/i915: Flip guc_id allocation partition
On 13.01.2022 00:26, Matthew Brost wrote: > On Thu, Jan 13, 2022 at 12:21:17AM +0100, Michal Wajdeczko wrote: >> On 11.01.2022 17:30, Matthew Brost wrote: ... >>> @@ -1863,6 +1861,33 @@ static void guc_submit_request(struct i915_request >>> *rq) >>> spin_unlock_irqrestore(&sched_engine->lock, flags); >>> } >>> >>> +static int new_mlrc_guc_id(struct intel_guc *guc, struct intel_context *ce) >>> +{ >>> + int ret; >>> + >>> + GEM_BUG_ON(!intel_context_is_parent(ce)); >>> + GEM_BUG_ON(!guc->submission_state.guc_ids_bitmap); >>> + >>> + ret = bitmap_find_free_region(guc->submission_state.guc_ids_bitmap, >>> + NUMBER_MULTI_LRC_GUC_ID(guc), >>> + order_base_2(ce->parallel.number_children >>> + + 1)); >> >> btw, is there any requirement (GuC ABI ?) that allocated ids need >> to be allocated with power of 2 alignment ? I don't think that we >> must optimize that hard and in some cases waste extra ids (as we might >> be limited on some configs) >> > > No pow2 requirement in GuC ABI, bitmaps only work on pow2 alignment and > didn't optmize this. > there is a slower variant of "find" function: bitmap_find_next_zero_area - find a contiguous aligned zero area that does not have this limitation .. >>> @@ -1989,6 +2008,14 @@ static int pin_guc_id(struct intel_guc *guc, struct >>> intel_context *ce) >>> >>> GEM_BUG_ON(atomic_read(&ce->guc_id.ref)); >>> >>> + if (unlikely(intel_context_is_parent(ce) && >>> +!guc->submission_state.guc_ids_bitmap)) { >>> + guc->submission_state.guc_ids_bitmap = >>> + bitmap_zalloc(NUMBER_MULTI_LRC_GUC_ID(guc), GFP_KERNEL); >>> + if (!guc->submission_state.guc_ids_bitmap) >>> + return -ENOMEM; >>> + } >> >> maybe move this chunk to new_mlrc_guc_id() ? >> or we can't due to the spin_lock below ? >> but then how do you protect guc_ids_bitmap pointer itself ? >> > > Can't use GFP_KERNEL inside a spin lock... > ok, but what if there will be two or more parallel calls to pin_guc_id() with all being first parent context? each will see NULL guc_ids_bitmap.. or there is another layer of synchronization? -Michal
Re: [Intel-gfx] [PATCH] drm/i915/guc: Check ctx while waiting for response
On 02.06.2022 19:21, Zhanjun Dong wrote: > We are seeing error message of "No response for request". Some cases happened > while waiting for response and reset/suspend action was triggered. In this > case, no response is not an error, active requests will be cancelled. > > This patch will handle this condition and change the error message into > debug message. > > Signed-off-by: Zhanjun Dong > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 21 ++--- > 1 file changed, 14 insertions(+), 7 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > index f01325cd1b62..a30a388877e2 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > @@ -467,7 +467,7 @@ static int ct_write(struct intel_guc_ct *ct, > * * 0 response received (status is valid) > * * -ETIMEDOUT no response within hardcoded timeout > */ > -static int wait_for_ct_request_update(struct ct_request *req, u32 *status) > +static int wait_for_ct_request_update(struct ct_request *req, u32 *status, > struct intel_guc_ct *ct) if you need to add "intel_guc_ct *ct" param then make it the first one > { > int err; > > @@ -481,12 +481,14 @@ static int wait_for_ct_request_update(struct ct_request > *req, u32 *status) > #define GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS 10 > #define GUC_CTB_RESPONSE_TIMEOUT_LONG_MS 1000 > #define done \ > - (FIELD_GET(GUC_HXG_MSG_0_ORIGIN, READ_ONCE(req->status)) == \ > + (!intel_guc_ct_enabled(ct) || FIELD_GET(GUC_HXG_MSG_0_ORIGIN, > READ_ONCE(req->status)) == \ >GUC_HXG_ORIGIN_GUC) > err = wait_for_us(done, GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS); > if (err) > err = wait_for(done, GUC_CTB_RESPONSE_TIMEOUT_LONG_MS); > #undef done > + if (!intel_guc_ct_enabled(ct)) > + err = -ECANCELED; > > *status = req->status; > return err; > @@ -703,11 +705,15 @@ static int ct_send(struct intel_guc_ct *ct, > > intel_guc_notify(ct_to_guc(ct)); > > - err = wait_for_ct_request_update(&request, status); > + err = wait_for_ct_request_update(&request, status, ct); > g2h_release_space(ct, GUC_CTB_HXG_MSG_MAX_LEN); > if (unlikely(err)) { > - CT_ERROR(ct, "No response for request %#x (fence %u)\n", > - action[0], request.fence); > + if (unlikely(err == ECANCELED)) you are looking for -ECANCELED and I guess you can safely drop "unlikely" hint here > + CT_DEBUG(ct, "Request %#x (fence %u) cancelled as CTB > is disabled\n", > + action[0], request.fence); > + else > + CT_ERROR(ct, "No response for request %#x (fence %u)\n", > + action[0], request.fence); > goto unlink; > } > > @@ -771,8 +777,9 @@ int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 > *action, u32 len, > > ret = ct_send(ct, action, len, response_buf, response_buf_size, > &status); > if (unlikely(ret < 0)) { > - CT_ERROR(ct, "Sending action %#x failed (%pe) status=%#X\n", > - action[0], ERR_PTR(ret), status); > + if (likely(ret != ECANCELED)) ditto ,Michal > + CT_ERROR(ct, "Sending action %#x failed (%pe) > status=%#X\n", > + action[0], ERR_PTR(ret), status); > } else if (unlikely(ret)) { > CT_DEBUG(ct, "send action %#x returned %d (%#x)\n", >action[0], ret, ret);
Re: [PATCH] drm/i915: Flip guc_id allocation partition
On 13.01.2022 17:27, Matthew Brost wrote: > Move the multi-lrc guc_id from the lower allocation partition (0 to > number of multi-lrc guc_ids) to upper allocation partition (number of > single-lrc to max guc_ids). > > This will help when a native driver transitions to a PF after driver > load time. If the perma-pin guc_ids (kernel contexts) are in a low range > it is easy reduce total number of guc_ids as the allocated slrc are in a > valid range the mlrc range moves to an unused range. Assuming no mlrc > are allocated and few slrc are used the native to PF transition is > seamless for the guc_id resource. > > v2: > (Michal / Tvrtko) > - Add an explaination to commit message of why this patch is needed > (Michal / Piotr) > - Replace marcos with functions > (Michal) > - Rework logic flow in new_mlrc_guc_id > - Unconditionally call bitmap_free > v3: > (Michal) > - Move allocation of mlrc bitmap back submission init > (CI) > - Resend for CI > > Signed-off-by: Matthew Brost > --- > .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 77 ++- > 1 file changed, 56 insertions(+), 21 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > index 23a40f10d376d..fce58365b3ff8 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > @@ -138,17 +138,6 @@ guc_create_parallel(struct intel_engine_cs **engines, > > #define GUC_REQUEST_SIZE 64 /* bytes */ > > -/* > - * We reserve 1/16 of the guc_ids for multi-lrc as these need to be > contiguous > - * per the GuC submission interface. A different allocation algorithm is used > - * (bitmap vs. ida) between multi-lrc and single-lrc hence the reason to > - * partition the guc_id space. We believe the number of multi-lrc contexts in > - * use should be low and 1/16 should be sufficient. Minimum of 32 guc_ids for > - * multi-lrc. > - */ > -#define NUMBER_MULTI_LRC_GUC_ID(guc) \ > - ((guc)->submission_state.num_guc_ids / 16) > - > /* > * Below is a set of functions which control the GuC scheduling state which > * require a lock. > @@ -1746,6 +1735,7 @@ void intel_guc_submission_reset_finish(struct intel_guc > *guc) > } > > static void destroyed_worker_func(struct work_struct *w); > +static int number_mlrc_guc_id(struct intel_guc *guc); > > /* > * Set up the memory resources to be shared with the GuC (via the GGTT) > @@ -1778,7 +1768,7 @@ int intel_guc_submission_init(struct intel_guc *guc) > destroyed_worker_func); > > guc->submission_state.guc_ids_bitmap = > - bitmap_zalloc(NUMBER_MULTI_LRC_GUC_ID(guc), GFP_KERNEL); > + bitmap_zalloc(number_mlrc_guc_id(guc), GFP_KERNEL); to fully benefit from the id partition flip we likely will have to allocate bitmap 'just-in-time' when first mlrc id is needed so something like you had in early rev but abandon to avoid alloc inside spinlock - but I'm wondering why we can't alloc bitmap for mlrc case, while we allow allocation for slrc (as ida_simple_get may alloc, no? > if (!guc->submission_state.guc_ids_bitmap) > return -ENOMEM; > > @@ -1864,6 +1854,57 @@ static void guc_submit_request(struct i915_request *rq) > spin_unlock_irqrestore(&sched_engine->lock, flags); > } > > +/* > + * We reserve 1/16 of the guc_ids for multi-lrc as these need to be > contiguous > + * per the GuC submission interface. A different allocation algorithm is used > + * (bitmap vs. ida) between multi-lrc and single-lrc hence the reason to > + * partition the guc_id space. We believe the number of multi-lrc contexts in > + * use should be low and 1/16 should be sufficient. do we have any other numbers as guideline ? while it is easy assumption that 1/16 from 64K contexts may be sufficient, what about 1/16 of 1K contexts ? will that work too ? also, do we have to make hard split ? what if there will be no users for mlrc but more slrc contexts would be beneficial ? or the opposite ? > + */ > +#define MLRC_GUC_ID_RATIO16 > + > +static int number_mlrc_guc_id(struct intel_guc *guc) > +{ > + return guc->submission_state.num_guc_ids / MLRC_GUC_ID_RATIO; > +} > + > +static int number_slrc_guc_id(struct intel_guc *guc) > +{ > + return guc->submission_state.num_guc_ids - number_mlrc_guc_id(guc); > +} > + > +static int mlrc_guc_id_base(struct intel_guc *guc) > +{ > + return number_slrc_guc_id(guc); > +} > + > +static int new_mlrc_guc_id(struct intel_guc *guc, struct intel_context *ce) > +{ > + int ret; > + > + GEM_BUG_ON(!intel_context_is_parent(ce)); > + GEM_BUG_ON(!guc->submission_state.guc_ids_bitmap); > + > + ret = bitmap_find_free_region(guc->submission_state.guc_ids_bitmap, > +number_mlrc_guc_id(guc), > +order_base_2(ce->parallel.number_children > +
Re: [PATCH v3 1/4] drm/i915/guc: Add fetch of hwconfig table
On 08.02.2022 22:05, Jordan Justen wrote: > From: John Harrison > > Implement support for fetching the hardware description table from the > GuC. The call is made twice - once without a destination buffer to > query the size and then a second time to fill in the buffer. > > Note that the table is only available on ADL-P and later platforms. > > Cc: Michal Wajdeczko > Signed-off-by: Rodrigo Vivi > Signed-off-by: John Harrison > Reviewed-by: Matthew Brost > --- > drivers/gpu/drm/i915/Makefile | 1 + > .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 1 + > .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 4 + > drivers/gpu/drm/i915/gt/uc/intel_guc.h| 3 + > .../gpu/drm/i915/gt/uc/intel_guc_hwconfig.c | 151 ++ > .../gpu/drm/i915/gt/uc/intel_guc_hwconfig.h | 19 +++ > drivers/gpu/drm/i915/gt/uc/intel_uc.c | 6 + > 7 files changed, 185 insertions(+) > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.h > > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile > index 6836b020a5be..ba9b6557d59d 100644 > --- a/drivers/gpu/drm/i915/Makefile > +++ b/drivers/gpu/drm/i915/Makefile > @@ -192,6 +192,7 @@ i915-y += gt/uc/intel_uc.o \ > gt/uc/intel_guc_rc.o \ > gt/uc/intel_guc_slpc.o \ > gt/uc/intel_guc_submission.o \ > + gt/uc/intel_guc_hwconfig.o \ nit: I guess ordering of files (by name) is also desired in makefiles > gt/uc/intel_huc.o \ > gt/uc/intel_huc_debugfs.o \ > gt/uc/intel_huc_fw.o > diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > index fe5d7d261797..4a61c819f32b 100644 > --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > @@ -137,6 +137,7 @@ enum intel_guc_action { > INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION = 0x1009, > INTEL_GUC_ACTION_SETUP_PC_GUCRC = 0x3004, > INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000, > + INTEL_GUC_ACTION_GET_HWCONFIG = 0x4100, > INTEL_GUC_ACTION_REGISTER_CONTEXT = 0x4502, > INTEL_GUC_ACTION_DEREGISTER_CONTEXT = 0x4503, > INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER = 0x4505, > diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h > b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h > index 488b6061ee89..f9e2a6aaef4a 100644 > --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h > +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h > @@ -8,6 +8,10 @@ > > enum intel_guc_response_status { > INTEL_GUC_RESPONSE_STATUS_SUCCESS = 0x0, > + INTEL_GUC_RESPONSE_NOT_SUPPORTED = 0x20, > + INTEL_GUC_RESPONSE_NO_ATTRIBUTE_TABLE = 0x201, > + INTEL_GUC_RESPONSE_NO_DECRYPTION_KEY = 0x202, > + INTEL_GUC_RESPONSE_DECRYPTION_FAILED = 0x204, > INTEL_GUC_RESPONSE_STATUS_GENERIC_FAIL = 0xF000, > }; > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > index f9240d4baa69..ce2ff4bb0fd5 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > @@ -13,6 +13,7 @@ > #include "intel_guc_fw.h" > #include "intel_guc_fwif.h" > #include "intel_guc_ct.h" > +#include "intel_guc_hwconfig.h" > #include "intel_guc_log.h" > #include "intel_guc_reg.h" > #include "intel_guc_slpc_types.h" > @@ -37,6 +38,8 @@ struct intel_guc { > struct intel_guc_ct ct; > /** @slpc: sub-structure containing SLPC related data and objects */ > struct intel_guc_slpc slpc; > + /** @hwconfig: hardware configuration KLV table */ nit: "@hwconfig: data related to hardware configuration KLV blob" > + struct intel_guc_hwconfig hwconfig; > > /** @sched_engine: Global engine used to submit requests to GuC */ > struct i915_sched_engine *sched_engine; > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c > new file mode 100644 > index ..ce6088f112d4 > --- /dev/null > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c > @@ -0,0 +1,151 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright © 2021 Intel Corporation 2022 ? > + */ > + > +#include "gt/intel_gt.h" > +#include "i915_drv.h" > +#include "i915_memcpy.h" > +#include "intel_guc_hwconfig.h" > + > +static inline struct intel_guc *hwconfig_to_guc(struct intel_guc_hwconfig > *hwconfig) no need for expli
Re: [PATCH v3 4/4] drm/i915/guc: Verify hwconfig blob matches supported format
On 08.02.2022 22:05, Jordan Justen wrote: > i915_drm.h now defines the format of the returned > DRM_I915_QUERY_HWCONFIG_BLOB query item. Since i915 receives this from > the black box GuC software, it should verify that the data matches > that format before sending it to user-space. > > The verification makes a single simple pass through the blob contents, > so this verification step should not add a significant amount of init > time to i915. > > v3: > * Add various changes suggested by Tvrtko > > Signed-off-by: Jordan Justen > --- > .../gpu/drm/i915/gt/uc/intel_guc_hwconfig.c | 56 ++- > 1 file changed, 53 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c > index ce6088f112d4..350a0517b9f0 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c > @@ -71,7 +71,52 @@ static int guc_hwconfig_discover_size(struct > intel_guc_hwconfig *hwconfig) > return 0; > } > > -static int guc_hwconfig_fill_buffer(struct intel_guc_hwconfig *hwconfig) > +static int verify_hwconfig_blob(struct drm_device *drm, no need to pass drm as you can use: + struct intel_guc *guc = hwconfig_to_guc(hwconfig); + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; > + const struct intel_guc_hwconfig *hwconfig) > +{ > + struct drm_i915_query_hwconfig_blob_item *pos; > + u32 remaining; > + > + if (hwconfig->size % 4 != 0 || hwconfig->ptr == NULL) size alignment could be verified in guc_hwconfig_discover_size() nit: instead of hardcoded 4 you may use 'sizeof(u32)' nit: and IS_ALIGNED and non-null ptr shall be enforced with GEM_BUG_ON as you are calling this function after memcpy > + return -EINVAL; > + > + pos = hwconfig->ptr; add line space and please update below multi-line comments format to /* * blah... > + /* The number of dwords in the blob to validate. Each loop > + * pass will process at least 2 dwords corresponding to the > + * key and length fields of the item. In addition, the length > + * field of the item indicates the length of the data array, > + * and that number of dwords will be processed (skipped) as > + * well. > + */ > + remaining = hwconfig->size / 4; > + > + while (remaining > 0) { > + /* Each item requires at least 2 dwords for the key > + * and length fields. If the length field is 0, then > + * the data array would be of length 0. > + */ > + if (remaining < 2) > + return -EINVAL; > + /* remaining >= 2, so subtracting 2 is ok, whereas > + * adding 2 to pos->length could overflow. > + */ > + if (pos->length > remaining - 2) > + return -EINVAL; > + /* The length check above ensures that the adjustment > + * of the remaining variable will not underflow, and > + * that the adjustment of the pos variable will not > + * pass the end of the blob data. > + */ > + remaining -= 2 + pos->length; > + pos = (void *)&pos->data[pos->length]; > + } btw, if it needs comments then it is too complicated ;) > + > + drm_dbg(drm, "hwconfig blob format is valid\n"); not sure if we need this since we have error message in case of failure maybe better to add dbg message why we claim it is invalid > + return 0; > +} > + > +static int guc_hwconfig_fill_buffer(struct drm_device *drm, no need to pass drm > + struct intel_guc_hwconfig *hwconfig) > { > struct intel_guc *guc = hwconfig_to_guc(hwconfig); > struct i915_vma *vma; > @@ -88,8 +133,13 @@ static int guc_hwconfig_fill_buffer(struct > intel_guc_hwconfig *hwconfig) > ggtt_offset = intel_guc_ggtt_offset(guc, vma); > > ret = __guc_action_get_hwconfig(hwconfig, ggtt_offset, hwconfig->size); > - if (ret >= 0) > + if (ret >= 0) { > memcpy(hwconfig->ptr, vaddr, hwconfig->size); > + if (verify_hwconfig_blob(drm, hwconfig)) { > + drm_err(drm, "Ignoring invalid hwconfig blob received > from GuC!\n"); > + ret = -EINVAL; btw, since we are about to release blob on verification failure, shouldn't we hexdump whole (or part of) blob somewhere for investigations ? or maybe we should expose this blob in debugfs, and do it regardless if it is valid or not, and just fail ioctl if blob is believed to be corrupted. ~Michal > + } > + } > > i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP); > > @@ -141,7 +191,7 @@ int intel_guc_hwconfig_init(struct intel_guc_hwconfig > *hwconfig) > return -ENOMEM; > } > > - ret = guc_hwconfig_fi
Re: [PATCH v3 01/11] drm/i915: Move display and media IP version to runtime info
On 01.09.2022 09:45, Jani Nikula wrote: > On Wed, 31 Aug 2022, Radhakrishna Sripada > wrote: ... >> struct ip_version graphics; >> +struct ip_version media; >> +struct ip_version display; > > The runtime display info is now in an unnamed struct under struct > intel_runtime_info below, and this belongs there. > > There's also some pressure to name it, and "display" would be the name, > so this would collide. > > Seems like all of the above are overly generic names, including the > pre-existing "graphics". Something to consider. maybe struct { struct { struct ip_version version; ... } graphics; struct { struct ip_version version; ... } media; struct { struct ip_version version; ... } display; } runtime; then drm_printf(p, "display version: %u.%02u\n", runtime->display.version.ver, runtime->display.version.rel); ... Michal
Re: [PATCH v2 09/21] drm/i915/guc: Define CTB based TLB invalidation routines
On 14.07.2022 14:06, Mauro Carvalho Chehab wrote: > From: Prathap Kumar Valsan > > Add routines to interface with GuC firmware for TLB invalidation. > > Signed-off-by: Prathap Kumar Valsan > Cc: Bruce Chang > Cc: Michal Wajdeczko > Cc: Matthew Brost > Cc: Chris Wilson > Signed-off-by: Mauro Carvalho Chehab > --- > > To avoid mailbombing on a large number of people, only mailing lists were C/C > on the cover. > See [PATCH v2 00/21] at: > https://lore.kernel.org/all/cover.1657800199.git.mche...@kernel.org/ > > .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 35 +++ > drivers/gpu/drm/i915/gt/uc/intel_guc.c| 90 ++ > drivers/gpu/drm/i915/gt/uc/intel_guc.h| 13 +++ > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 24 - > drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 6 ++ > .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 91 ++- > 6 files changed, 253 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > index 4ef9990ed7f8..2e39d8df4c82 100644 > --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > @@ -134,6 +134,10 @@ enum intel_guc_action { > INTEL_GUC_ACTION_REGISTER_CONTEXT_MULTI_LRC = 0x4601, > INTEL_GUC_ACTION_CLIENT_SOFT_RESET = 0x5507, > INTEL_GUC_ACTION_SET_ENG_UTIL_BUFF = 0x550A, > + INTEL_GUC_ACTION_NOTIFY_MEMORY_CAT_ERROR = 0x6000, should this be part of this patch ? > + INTEL_GUC_ACTION_PAGE_FAULT_NOTIFICATION = 0x6001, > + INTEL_GUC_ACTION_TLB_INVALIDATION = 0x7000, > + INTEL_GUC_ACTION_TLB_INVALIDATION_DONE = 0x7001, can we document layout of these actions ? > INTEL_GUC_ACTION_STATE_CAPTURE_NOTIFICATION = 0x8002, > INTEL_GUC_ACTION_NOTIFY_FLUSH_LOG_BUFFER_TO_FILE = 0x8003, > INTEL_GUC_ACTION_NOTIFY_CRASH_DUMP_POSTED = 0x8004, > @@ -177,4 +181,35 @@ enum intel_guc_state_capture_event_status { > > #define INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_MASK 0x00FF > > +#define INTEL_GUC_TLB_INVAL_TYPE_SHIFT 0 > +#define INTEL_GUC_TLB_INVAL_MODE_SHIFT 8 can we stop using SHIFT-based definitions and start using MASK-based instead ? then we will be able to use FIELD_PREP/GET like we do for i915_reg > +/* Flush PPC or SMRO caches along with TLB invalidation request */ > +#define INTEL_GUC_TLB_INVAL_FLUSH_CACHE (1 << 31) > + > +enum intel_guc_tlb_invalidation_type { > + INTEL_GUC_TLB_INVAL_GUC = 0x3, > +}; > + > +/* > + * 0: Heavy mode of Invalidation: > + * The pipeline of the engine(s) for which the invalidation is targeted to is > + * blocked, and all the in-flight transactions are guaranteed to be Globally > + * Observed before completing the TLB invalidation > + * 1: Lite mode of Invalidation: > + * TLBs of the targeted engine(s) are immediately invalidated. > + * In-flight transactions are NOT guaranteed to be Globally Observed before > + * completing TLB invalidation. > + * Light Invalidation Mode is to be used only when > + * it can be guaranteed (by SW) that the address translations remain > invariant > + * for the in-flight transactions across the TLB invalidation. In other > words, > + * this mode can be used when the TLB invalidation is intended to clear out > the > + * stale cached translations that are no longer in use. Light Invalidation > Mode > + * is much faster than the Heavy Invalidation Mode, as it does not wait for > the > + * in-flight transactions to be GOd. > + */ either drop this comment or squash with patch 10/21 to fix it > +enum intel_guc_tlb_inval_mode { > + INTEL_GUC_TLB_INVAL_MODE_HEAVY = 0x0, > + INTEL_GUC_TLB_INVAL_MODE_LITE = 0x1, > +}; > + > #endif /* _ABI_GUC_ACTIONS_ABI_H */ > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > index 2706a8c65090..5c59f9b144a3 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > @@ -855,6 +855,96 @@ int intel_guc_self_cfg64(struct intel_guc *guc, u16 key, > u64 value) > return __guc_self_cfg(guc, key, 2, value); > } > > +static int guc_send_invalidate_tlb(struct intel_guc *guc, u32 *action, u32 > size) nit: maybe since MMIO TLB has moved to dedicated file, we can do the same with GUC TLB code like "intel_guc_tlb.c" ? > +{ > + struct intel_guc_tlb_wait _wq, *wq = &_wq; > + DEFINE_WAIT_FUNC(wait, woken_wake_function); > + int err = 0; > + u32 seqno; > + > + init_waitqueue_head(&_wq.wq); > + > + if (xa_alloc_cyclic_irq(&guc->tl
Re: [PATCH v2 16/21] drm/i915: Define GuC Based TLB invalidation routines
On 14.07.2022 14:06, Mauro Carvalho Chehab wrote: > From: Prathap Kumar Valsan > > Add routines to interface with GuC firmware for selective TLB invalidation > supported on XeHP. > > Signed-off-by: Prathap Kumar Valsan > Cc: Matthew Brost > Signed-off-by: Mauro Carvalho Chehab > --- > > To avoid mailbombing on a large number of people, only mailing lists were C/C > on the cover. > See [PATCH v2 00/21] at: > https://lore.kernel.org/all/cover.1657800199.git.mche...@kernel.org/ > > .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 3 + > drivers/gpu/drm/i915/gt/uc/intel_guc.c| 90 +++ > drivers/gpu/drm/i915/gt/uc/intel_guc.h| 10 +++ > drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 3 + > 4 files changed, 106 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > index fb0af33e43cc..5c019856a269 100644 > --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h > @@ -188,6 +188,9 @@ enum intel_guc_state_capture_event_status { > #define INTEL_GUC_TLB_INVAL_FLUSH_CACHE (1 << 31) > > enum intel_guc_tlb_invalidation_type { > + INTEL_GUC_TLB_INVAL_FULL = 0x0, > + INTEL_GUC_TLB_INVAL_PAGE_SELECTIVE = 0x1, > + INTEL_GUC_TLB_INVAL_PAGE_SELECTIVE_CTX = 0x2, > INTEL_GUC_TLB_INVAL_GUC = 0x3, > }; > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > index 8a104a292598..98260a7bc90b 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > @@ -923,6 +923,96 @@ static int guc_send_invalidate_tlb(struct intel_guc > *guc, u32 *action, u32 size) > return err; > } > > + /* Full TLB invalidation */ > +int intel_guc_invalidate_tlb_full(struct intel_guc *guc, > + enum intel_guc_tlb_inval_mode mode) > +{ > + u32 action[] = { > + INTEL_GUC_ACTION_TLB_INVALIDATION, > + 0, > + INTEL_GUC_TLB_INVAL_FULL << INTEL_GUC_TLB_INVAL_TYPE_SHIFT | > + mode << INTEL_GUC_TLB_INVAL_MODE_SHIFT | > + INTEL_GUC_TLB_INVAL_FLUSH_CACHE, > + }; > + > + if (!INTEL_GUC_SUPPORTS_TLB_INVALIDATION(guc)) { > + DRM_ERROR("Tlb invalidation: Operation not supported in this > platform!\n"); s/Tlb/TLB and use drm_err() or even consider GEM_BUG_ON() as this looks more like a coding mistake if we will be here, no ? > + return 0; > + } > + > + return guc_send_invalidate_tlb(guc, action, ARRAY_SIZE(action)); > +} > + > +/* > + * Selective TLB Invalidation for Address Range: > + * TLB's in the Address Range is Invalidated across all engines. > + */ > +int intel_guc_invalidate_tlb_page_selective(struct intel_guc *guc, > + enum intel_guc_tlb_inval_mode mode, > + u64 start, u64 length) > +{ > + u64 vm_total = BIT_ULL(INTEL_INFO(guc_to_gt(guc)->i915)->ppgtt_size); > + u32 address_mask = (ilog2(length) - ilog2(I915_GTT_PAGE_SIZE_4K)); drop extra ( ) > + u32 full_range = vm_total == length; bool ? > + u32 action[] = { > + INTEL_GUC_ACTION_TLB_INVALIDATION, > + 0, > + INTEL_GUC_TLB_INVAL_PAGE_SELECTIVE << > INTEL_GUC_TLB_INVAL_TYPE_SHIFT | > + mode << INTEL_GUC_TLB_INVAL_MODE_SHIFT | > + INTEL_GUC_TLB_INVAL_FLUSH_CACHE, > + 0, > + full_range ? full_range : lower_32_bits(start), > + full_range ? 0 : upper_32_bits(start), > + full_range ? 0 : address_mask, > + }; > + > + if (!INTEL_GUC_SUPPORTS_TLB_INVALIDATION_SELECTIVE(guc)) { > + DRM_ERROR("Tlb invalidation: Operation not supported in this > platform!\n"); as above > + return 0; > + } > + > + GEM_BUG_ON(!IS_ALIGNED(start, I915_GTT_PAGE_SIZE_4K)); > + GEM_BUG_ON(!IS_ALIGNED(length, I915_GTT_PAGE_SIZE_4K)); > + GEM_BUG_ON(range_overflows(start, length, vm_total)); > + > + return guc_send_invalidate_tlb(guc, action, ARRAY_SIZE(action)); > +} > + > +/* > + * Selective TLB Invalidation for Context: > + * Invalidates all TLB's for a specific context across all engines. > + */ > +int intel_guc_invalidate_tlb_page_selective_ctx(struct intel_guc *guc, > + enum intel_guc_tlb_inval_mode > mode, > + u64 start, u64 length, u32 > ctxid) > +{ > + u64 vm_total = BIT_ULL(INTEL_INFO(guc_to_gt(guc)->i915)->ppgtt_size); > + u32 address_mask = (ilog2(length) - ilog2(I915_GTT_PAGE_SIZE_4K)); drop ( ) > + u32 full_range = vm_total == length; bool > + u32 action[] = { > + INTEL_GUC_ACTION_TLB_INVALIDATION, > + 0, > + INTEL_GUC_TLB_INVAL_PAGE_SELECTIVE_CTX << > INTEL_GUC_TLB
Re: [Intel-gfx] [PATCH 6/6] drm/i915/guc: Don't abort on CTB_UNUSED status
On 28.07.2022 04:42, john.c.harri...@intel.com wrote: > From: John Harrison > > When the KMD sends a CLIENT_RESET request to GuC (as part of the > suspend sequence), GuC will mark the CTB buffer as 'UNUSED'. If the hmm, GuC shouldn't do that on CLIENT_RESET, GuC shall only mark CTB as UNUSED when we explicitly disable CTB using CONTROL_CTB as only then CTB descriptors are known to be valid > KMD then checked the CTB queue, it would see a non-zero status value > and report the buffer as corrupted. > > Technically, no G2H messages should be received once the CLIENT_RESET > has been sent. However, if a context was outstanding on an engine then > it would get reset and a reset notification would be sent. So, don't > actually treat UNUSED as a catastrophic error. Just flag it up as > unexpected and keep going. we should have already marked locally that CTB is disabled, either as part of the explicit disabling of CTB with CONTROL_CTB, or implicit due to issued CLIENT_RESET, but in both cases we shouldn't try to read CTB any more, even it there are any outstanding messages ... is this due to a race with ct->enabled ? > > Signed-off-by: John Harrison > --- > .../i915/gt/uc/abi/guc_communication_ctb_abi.h | 8 +--- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 18 -- > 2 files changed, 21 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h > b/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h > index df83c1cc7c7a6..28b8387f97b77 100644 > --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h > +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h > @@ -37,6 +37,7 @@ > * | | | - _`GUC_CTB_STATUS_OVERFLOW` = 1 (head/tail too large) > | > * | | | - _`GUC_CTB_STATUS_UNDERFLOW` = 2 (truncated message) > | > * | | | - _`GUC_CTB_STATUS_MISMATCH` = 4 (head/tail modified) > | > + * | | | - _`GUC_CTB_STATUS_UNUSED` = 8 (CTB is not in use) > | > * > +---+---+--+ > * |...| | RESERVED = MBZ > | > * > +---+---+--+ > @@ -49,9 +50,10 @@ struct guc_ct_buffer_desc { > u32 tail; > u32 status; > #define GUC_CTB_STATUS_NO_ERROR 0 > -#define GUC_CTB_STATUS_OVERFLOW (1 << 0) > -#define GUC_CTB_STATUS_UNDERFLOW (1 << 1) > -#define GUC_CTB_STATUS_MISMATCH (1 << 2) > +#define GUC_CTB_STATUS_OVERFLOW BIT(0) > +#define GUC_CTB_STATUS_UNDERFLOW BIT(1) > +#define GUC_CTB_STATUS_MISMATCH BIT(2) > +#define GUC_CTB_STATUS_UNUSEDBIT(3) nit: our goal was to use plain C definitions in ABI headers as much as possible without introducing any dependency on external macros > u32 reserved[13]; > } __packed; > static_assert(sizeof(struct guc_ct_buffer_desc) == 64); > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > index f01325cd1b625..11b5d4ddb19ce 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > @@ -816,8 +816,22 @@ static int ct_read(struct intel_guc_ct *ct, struct > ct_incoming_msg **msg) > if (unlikely(ctb->broken)) > return -EPIPE; > > - if (unlikely(desc->status)) > - goto corrupted; > + if (unlikely(desc->status)) { > + u32 status = desc->status; > + > + if (status & GUC_CTB_STATUS_UNUSED) { > + /* > + * Potentially valid if a CLIENT_RESET request resulted > in > + * contexts/engines being reset. But should never > happen as > + * no contexts should be active when CLIENT_RESET is > sent. > + */ > + CT_ERROR(ct, "Unexpected G2H after GuC has stopped!\n"); > + status &= ~GUC_CTB_STATUS_UNUSED; do you really want to continue read messages from already disabled CTB ? maybe instead of clearing GUC_CTB_STATUS_UNUSED bit we should just return? Michal > + } > + > + if (status) > + goto corrupted; > + } > > GEM_BUG_ON(head > size); >
Re: [RFC PATCH 05/97] drm/i915/guc: use probe_error log for CT enablement failure
On 06.05.2021 21:13, Matthew Brost wrote: > From: Daniele Ceraolo Spurio > > We have a couple of failure injection points in the CT enablement path, > so we need to use i915_probe_error() to select the appropriate log level. > A new macro (CT_PROBE_ERROR) has been added to the set of CT logging > macros to be used in this scenario and upcoming ones. > > While adding the new macros, fix the underlying logging mechanics used > by the existing ones (DRM_DEV_* -> drm_*) and move the inlines to > before they're used inside the macros. > > Signed-off-by: Matthew Brost > Signed-off-by: Daniele Ceraolo Spurio > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 48 --- > 1 file changed, 25 insertions(+), 23 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > index fa9e048cc65f..25618649048f 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > @@ -7,14 +7,36 @@ > #include "intel_guc_ct.h" > #include "gt/intel_gt.h" > > +static inline struct intel_guc *ct_to_guc(struct intel_guc_ct *ct) > +{ > + return container_of(ct, struct intel_guc, ct); > +} > + > +static inline struct intel_gt *ct_to_gt(struct intel_guc_ct *ct) > +{ > + return guc_to_gt(ct_to_guc(ct)); > +} > + > +static inline struct drm_i915_private *ct_to_i915(struct intel_guc_ct *ct) > +{ > + return ct_to_gt(ct)->i915; > +} > + > +static inline struct drm_device *ct_to_drm(struct intel_guc_ct *ct) > +{ > + return &ct_to_i915(ct)->drm; > +} > + > #define CT_ERROR(_ct, _fmt, ...) \ > - DRM_DEV_ERROR(ct_to_dev(_ct), "CT: " _fmt, ##__VA_ARGS__) > + drm_err(ct_to_drm(_ct), "CT: " _fmt, ##__VA_ARGS__) > #ifdef CONFIG_DRM_I915_DEBUG_GUC > #define CT_DEBUG(_ct, _fmt, ...) \ > - DRM_DEV_DEBUG_DRIVER(ct_to_dev(_ct), "CT: " _fmt, ##__VA_ARGS__) > + drm_dbg(ct_to_drm(_ct), "CT: " _fmt, ##__VA_ARGS__) > #else > #define CT_DEBUG(...)do { } while (0) > #endif > +#define CT_PROBE_ERROR(_ct, _fmt, ...) \ > + i915_probe_error(ct_to_i915(ct), "CT: " _fmt, ##__VA_ARGS__); > > struct ct_request { > struct list_head link; > @@ -47,26 +69,6 @@ void intel_guc_ct_init_early(struct intel_guc_ct *ct) > INIT_WORK(&ct->requests.worker, ct_incoming_request_worker_func); > } > > -static inline struct intel_guc *ct_to_guc(struct intel_guc_ct *ct) > -{ > - return container_of(ct, struct intel_guc, ct); > -} > - > -static inline struct intel_gt *ct_to_gt(struct intel_guc_ct *ct) > -{ > - return guc_to_gt(ct_to_guc(ct)); > -} > - > -static inline struct drm_i915_private *ct_to_i915(struct intel_guc_ct *ct) > -{ > - return ct_to_gt(ct)->i915; > -} > - > -static inline struct device *ct_to_dev(struct intel_guc_ct *ct) > -{ > - return ct_to_i915(ct)->drm.dev; > -} > - > static inline const char *guc_ct_buffer_type_to_str(u32 type) > { > switch (type) { > @@ -264,7 +266,7 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct) > err_deregister: > ct_deregister_buffer(ct, INTEL_GUC_CT_BUFFER_TYPE_RECV); > err_out: > - CT_ERROR(ct, "Failed to open open CT channel (err=%d)\n", err); > + CT_PROBE_ERROR(ct, "Failed to open channel (err=%d)\n", err); nit: while here we can start using %pe to print error Reviewed-by: Michal Wajdeczko > return err; > } > >
Re: [RFC PATCH 07/97] drm/i915/guc: Remove sample_forcewake h2g action
On 06.05.2021 21:13, Matthew Brost wrote: > From: Rodrigo Vivi > > This action is no-op in the GuC side for a few versions already > and it is getting entirely removed soon, in an upcoming version. > > Time to remove before we face communication issues. > > Cc: Vinay Belgaumkar > Signed-off-by: Rodrigo Vivi > Signed-off-by: Matthew Brost Acked-by: Michal Wajdeczko > --- > drivers/gpu/drm/i915/gt/uc/intel_guc.c | 16 > drivers/gpu/drm/i915/gt/uc/intel_guc.h | 1 - > drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 4 > drivers/gpu/drm/i915/gt/uc/intel_uc.c | 4 > 4 files changed, 25 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > index adae04c47aab..ab2c8fe8cdfa 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > @@ -469,22 +469,6 @@ int intel_guc_to_host_process_recv_msg(struct intel_guc > *guc, > return 0; > } > > -int intel_guc_sample_forcewake(struct intel_guc *guc) > -{ > - struct drm_i915_private *dev_priv = guc_to_gt(guc)->i915; > - u32 action[2]; > - > - action[0] = INTEL_GUC_ACTION_SAMPLE_FORCEWAKE; > - /* WaRsDisableCoarsePowerGating:skl,cnl */ > - if (!HAS_RC6(dev_priv) || NEEDS_WaRsDisableCoarsePowerGating(dev_priv)) > - action[1] = 0; > - else > - /* bit 0 and 1 are for Render and Media domain separately */ > - action[1] = GUC_FORCEWAKE_RENDER | GUC_FORCEWAKE_MEDIA; > - > - return intel_guc_send(guc, action, ARRAY_SIZE(action)); > -} > - > /** > * intel_guc_auth_huc() - Send action to GuC to authenticate HuC ucode > * @guc: intel_guc structure > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > index bc2ba7d0626c..c20f3839de12 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > @@ -128,7 +128,6 @@ int intel_guc_send_mmio(struct intel_guc *guc, const u32 > *action, u32 len, > u32 *response_buf, u32 response_buf_size); > int intel_guc_to_host_process_recv_msg(struct intel_guc *guc, > const u32 *payload, u32 len); > -int intel_guc_sample_forcewake(struct intel_guc *guc); > int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset); > int intel_guc_suspend(struct intel_guc *guc); > int intel_guc_resume(struct intel_guc *guc); > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h > index 79c560d9c0b6..0f9afcde1d0b 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h > @@ -302,9 +302,6 @@ struct guc_ct_buffer_desc { > #define GUC_CT_MSG_ACTION_SHIFT 16 > #define GUC_CT_MSG_ACTION_MASK 0x > > -#define GUC_FORCEWAKE_RENDER (1 << 0) > -#define GUC_FORCEWAKE_MEDIA (1 << 1) > - > #define GUC_POWER_UNSPECIFIED0 > #define GUC_POWER_D0 1 > #define GUC_POWER_D1 2 > @@ -558,7 +555,6 @@ enum intel_guc_action { > INTEL_GUC_ACTION_ENTER_S_STATE = 0x501, > INTEL_GUC_ACTION_EXIT_S_STATE = 0x502, > INTEL_GUC_ACTION_SLPC_REQUEST = 0x3003, > - INTEL_GUC_ACTION_SAMPLE_FORCEWAKE = 0x3005, > INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000, > INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER = 0x4505, > INTEL_GUC_ACTION_DEREGISTER_COMMAND_TRANSPORT_BUFFER = 0x4506, > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c > b/drivers/gpu/drm/i915/gt/uc/intel_uc.c > index 892c1315ce49..ab0789d66e06 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c > @@ -502,10 +502,6 @@ static int __uc_init_hw(struct intel_uc *uc) > > intel_huc_auth(huc); > > - ret = intel_guc_sample_forcewake(guc); > - if (ret) > - goto err_log_capture; > - > if (intel_uc_uses_guc_submission(uc)) > intel_guc_submission_enable(guc); > >
Re: [RFC PATCH 30/97] drm/i915/uc: turn on GuC/HuC auto mode by default
On 06.05.2021 21:13, Matthew Brost wrote: > From: Daniele Ceraolo Spurio > > This will enable HuC loading for Gen11+ by default if the binaries > are available on the system. GuC submission still requires explicit > enabling by the user. > > Signed-off-by: Daniele Ceraolo Spurio > Signed-off-by: Matthew Brost > Cc: Michal Wajdeczko > Cc: John Harrison > --- > drivers/gpu/drm/i915/i915_params.h | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/i915_params.h > b/drivers/gpu/drm/i915/i915_params.h > index 14cd64cc61d0..a0575948ab61 100644 > --- a/drivers/gpu/drm/i915/i915_params.h > +++ b/drivers/gpu/drm/i915/i915_params.h > @@ -59,7 +59,7 @@ struct drm_printer; > param(int, disable_power_well, -1, 0400) \ > param(int, enable_ips, 1, 0600) \ > param(int, invert_brightness, 0, 0600) \ > - param(int, enable_guc, 0, 0400) \ > + param(int, enable_guc, -1, 0400) \ you also want to update param description from "(-1=auto, 0=disable [default], 1=GuC submission, 2=HuC load)"); to "(-1=auto [default], 0=disable, 1=GuC submission, 2=HuC load)"); > param(int, guc_log_level, -1, 0400) \ > param(char *, guc_firmware_path, NULL, 0400) \ > param(char *, huc_firmware_path, NULL, 0400) \ >
Re: [RFC PATCH 35/97] drm/i915/guc: Improve error message for unsolicited CT response
On 06.05.2021 21:13, Matthew Brost wrote: > Improve the error message when a unsolicited CT response is received by > printing fence that couldn't be found, the last fence, and all requests > with a response outstanding. > > Signed-off-by: Matthew Brost > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 10 +++--- > 1 file changed, 7 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > index 217ab3ebd1af..a76603537fa8 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > @@ -703,12 +703,16 @@ static int ct_handle_response(struct intel_guc_ct *ct, > struct ct_incoming_msg *r > found = true; > break; > } > - spin_unlock_irqrestore(&ct->requests.lock, flags); > - > if (!found) { > CT_ERROR(ct, "Unsolicited response (fence %u)\n", fence); > - return -ENOKEY; > + CT_ERROR(ct, "Could not find fence=%u, last_fence=%u\n", fence, > + ct->requests.last_fence); nit: this new wording may suggest that it's our fault, but that's not necessary true > + list_for_each_entry(req, &ct->requests.pending, link) > + CT_ERROR(ct, "request %u awaits response\n", > + req->fence); usually we don't send multiple requests that expects responses, so it's very likely that list with pending requests will be empty, and even if list is not empty, I'm not sure what is the relation between those pending requests to this unsolicited response, thus wondering how these extra errors could improve our debugging experience ? > + err = -ENOKEY; > } > + spin_unlock_irqrestore(&ct->requests.lock, flags); > > if (unlikely(err)) > return err; >
Re: [RFC PATCH 36/97] drm/i915/guc: Add non blocking CTB send function
On 06.05.2021 21:13, Matthew Brost wrote: > Add non blocking CTB send function, intel_guc_send_nb. In order to > support a non blocking CTB send function a spin lock is needed to spin lock was added in 16/97 > protect the CTB descriptors fields. Also the non blocking call must not > update the fence value as this value is owned by the blocking call > (intel_guc_send). all H2G messages are using "fence", nb variant also needs to update it > > The blocking CTB now must have a flow control mechanism to ensure the s/blocking/non-blocking > buffer isn't overrun. A lazy spin wait is used as we believe the flow > control condition should be rare with properly sized buffer. as this new nb function is still not used in this patch, then maybe better to move flow control to separate patch for easier review ? > > The function, intel_guc_send_nb, is exported in this patch but unused. > Several patches later in the series make use of this function. > > Signed-off-by: John Harrison > Signed-off-by: Matthew Brost > --- > drivers/gpu/drm/i915/gt/uc/intel_guc.h| 12 ++- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 96 +-- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h | 7 +- > 3 files changed, 105 insertions(+), 10 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > index c20f3839de12..4c0a367e41d8 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > @@ -75,7 +75,15 @@ static inline struct intel_guc *log_to_guc(struct > intel_guc_log *log) > static > inline int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len) > { > - return intel_guc_ct_send(&guc->ct, action, len, NULL, 0); > + return intel_guc_ct_send(&guc->ct, action, len, NULL, 0, 0); > +} > + > +#define INTEL_GUC_SEND_NBBIT(31) > +static > +inline int intel_guc_send_nb(struct intel_guc *guc, const u32 *action, u32 > len) > +{ > + return intel_guc_ct_send(&guc->ct, action, len, NULL, 0, > + INTEL_GUC_SEND_NB); > } > > static inline int > @@ -83,7 +91,7 @@ intel_guc_send_and_receive(struct intel_guc *guc, const u32 > *action, u32 len, > u32 *response_buf, u32 response_buf_size) > { > return intel_guc_ct_send(&guc->ct, action, len, > - response_buf, response_buf_size); > + response_buf, response_buf_size, 0); > } > > static inline void intel_guc_to_host_event_handler(struct intel_guc *guc) > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > index a76603537fa8..af7314d45a78 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > @@ -3,6 +3,11 @@ > * Copyright © 2016-2019 Intel Corporation > */ > > +#include > +#include > +#include > +#include > + > #include "i915_drv.h" > #include "intel_guc_ct.h" > #include "gt/intel_gt.h" > @@ -308,6 +313,7 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct) > if (unlikely(err)) > goto err_deregister; > > + ct->requests.last_fence = 1; not needed > ct->enabled = true; > > return 0; > @@ -343,10 +349,22 @@ static u32 ct_get_next_fence(struct intel_guc_ct *ct) > return ++ct->requests.last_fence; > } > > +static void write_barrier(struct intel_guc_ct *ct) { > + struct intel_guc *guc = ct_to_guc(ct); > + struct intel_gt *gt = guc_to_gt(guc); > + > + if (i915_gem_object_is_lmem(guc->ct.vma->obj)) { > + GEM_BUG_ON(guc->send_regs.fw_domains); > + intel_uncore_write_fw(gt->uncore, GEN11_SOFT_SCRATCH(0), 0); > + } else { > + wmb(); > + } > +} this chunk seems to be good candidate for separate patch that could be introduced earlier > + > static int ct_write(struct intel_guc_ct *ct, > const u32 *action, > u32 len /* in dwords */, > - u32 fence) > + u32 fence, u32 flags) > { > struct intel_guc_ct_buffer *ctb = &ct->ctbs.send; > struct guc_ct_buffer_desc *desc = ctb->desc; > @@ -393,9 +411,13 @@ static int ct_write(struct intel_guc_ct *ct, >FIELD_PREP(GUC_CTB_MSG_0_NUM_DWORDS, len) | >FIELD_PREP(GUC_CTB_MSG_0_FENCE, fence); > > - hxg = FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) | > - FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION | > - GUC_HXG_REQUEST_MSG_0_DATA0, action[0]); > + hxg = (flags & INTEL_GUC_SEND_NB) ? > + (FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_EVENT) | > + FIELD_PREP(GUC_HXG_EVENT_MSG_0_ACTION | > + GUC_HXG_EVENT_MSG_0_DATA0, action[0])) : > + (FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) | > + FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION | > +
Re: [RFC PATCH 37/97] drm/i915/guc: Add stall timer to non blocking CTB send function
On 06.05.2021 21:13, Matthew Brost wrote: > Implement a stall timer which fails H2G CTBs once a period of time > with no forward progress is reached to prevent deadlock. > > Also update to ct_write to return -EDEADLK rather than -EPIPE on a > corrupted descriptor. broken descriptor is really separate issue compared to no progress from GuC side, I would really like to keep old error code note that broken CTB descriptor is unrecoverable error, while on other hand, in theory, we could recover from temporary non-moving CTB > > Signed-off-by: John Harrison > Signed-off-by: Daniele Ceraolo Spurio > Signed-off-by: Matthew Brost > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 48 +-- > 1 file changed, 45 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > index af7314d45a78..4eab319d61be 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > @@ -69,6 +69,8 @@ static inline struct drm_device *ct_to_drm(struct > intel_guc_ct *ct) > #define CTB_H2G_BUFFER_SIZE (SZ_4K) > #define CTB_G2H_BUFFER_SIZE (SZ_4K) > > +#define MAX_US_STALL_CTB 100 nit: maybe we should make it a CONFIG value ? > + > struct ct_request { > struct list_head link; > u32 fence; > @@ -315,6 +317,7 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct) > > ct->requests.last_fence = 1; > ct->enabled = true; > + ct->stall_time = KTIME_MAX; > > return 0; > > @@ -378,7 +381,7 @@ static int ct_write(struct intel_guc_ct *ct, > unsigned int i; > > if (unlikely(ctb->broken)) > - return -EPIPE; > + return -EDEADLK; > > if (unlikely(desc->status)) > goto corrupted; > @@ -449,7 +452,7 @@ static int ct_write(struct intel_guc_ct *ct, > CT_ERROR(ct, "Corrupted descriptor head=%u tail=%u status=%#x\n", >desc->head, desc->tail, desc->status); > ctb->broken = true; > - return -EPIPE; > + return -EDEADLK; > } > > /** > @@ -494,6 +497,17 @@ static int wait_for_ct_request_update(struct ct_request > *req, u32 *status) > return err; > } > > +static inline bool ct_deadlocked(struct intel_guc_ct *ct) > +{ > + bool ret = ktime_us_delta(ktime_get(), ct->stall_time) > > + MAX_US_STALL_CTB; > + > + if (unlikely(ret)) > + CT_ERROR(ct, "CT deadlocked\n"); > + > + return ret; > +} > + > static inline bool ctb_has_room(struct intel_guc_ct_buffer *ctb, u32 len_dw) > { > struct guc_ct_buffer_desc *desc = ctb->desc; > @@ -505,6 +519,26 @@ static inline bool ctb_has_room(struct > intel_guc_ct_buffer *ctb, u32 len_dw) > return space >= len_dw; > } > > +static int has_room_nb(struct intel_guc_ct *ct, u32 len_dw) > +{ > + struct intel_guc_ct_buffer *ctb = &ct->ctbs.send; > + > + lockdep_assert_held(&ct->ctbs.send.lock); > + > + if (unlikely(!ctb_has_room(ctb, len_dw))) { > + if (ct->stall_time == KTIME_MAX) > + ct->stall_time = ktime_get(); > + > + if (unlikely(ct_deadlocked(ct))) > + return -EDEADLK; > + else > + return -EBUSY; > + } > + > + ct->stall_time = KTIME_MAX; > + return 0; > +} > + > static int ct_send_nb(struct intel_guc_ct *ct, > const u32 *action, > u32 len, > @@ -517,7 +551,7 @@ static int ct_send_nb(struct intel_guc_ct *ct, > > spin_lock_irqsave(&ctb->lock, spin_flags); > > - ret = ctb_has_room(ctb, len + 1); > + ret = has_room_nb(ct, len + 1); > if (unlikely(ret)) > goto out; > > @@ -561,11 +595,19 @@ static int ct_send(struct intel_guc_ct *ct, > retry: > spin_lock_irqsave(&ct->ctbs.send.lock, flags); > if (unlikely(!ctb_has_room(ctb, len + 1))) { > + if (ct->stall_time == KTIME_MAX) > + ct->stall_time = ktime_get(); > spin_unlock_irqrestore(&ct->ctbs.send.lock, flags); > + > + if (unlikely(ct_deadlocked(ct))) > + return -EDEADLK; > + likely, instead of duplicating code, you can reuse has_room_nb here > cond_resched(); > goto retry; > } > > + ct->stall_time = KTIME_MAX; > + > fence = ct_get_next_fence(ct); > request.fence = fence; > request.status = 0; >
Re: [RFC PATCH 38/97] drm/i915/guc: Optimize CTB writes and reads
On 06.05.2021 21:13, Matthew Brost wrote: > CTB writes are now in the path of command submission and should be > optimized for performance. Rather than reading CTB descriptor values > (e.g. head, tail, size) which could result in accesses across the PCIe size was removed from the descriptor in 25/97 > bus, store shadow local copies and only read/write the descriptor > values when absolutely necessary. maybe worth to add some words about caching available space ? > > Signed-off-by: John Harrison > Signed-off-by: Matthew Brost > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 78 +-- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h | 6 ++ > 2 files changed, 52 insertions(+), 32 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > index 4eab319d61be..77dfbc94dcc3 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > @@ -127,6 +127,10 @@ static void guc_ct_buffer_desc_init(struct > guc_ct_buffer_desc *desc) > static void guc_ct_buffer_reset(struct intel_guc_ct_buffer *ctb) > { > ctb->broken = false; > + ctb->tail = 0; > + ctb->head = 0; > + ctb->space = CIRC_SPACE(ctb->tail, ctb->head, ctb->size); > + > guc_ct_buffer_desc_init(ctb->desc); > } > > @@ -371,10 +375,8 @@ static int ct_write(struct intel_guc_ct *ct, > { > struct intel_guc_ct_buffer *ctb = &ct->ctbs.send; > struct guc_ct_buffer_desc *desc = ctb->desc; > - u32 head = desc->head; > - u32 tail = desc->tail; > + u32 tail = ctb->tail; > u32 size = ctb->size; > - u32 used; > u32 header; > u32 hxg; > u32 *cmds = ctb->cmds; > @@ -386,25 +388,14 @@ static int ct_write(struct intel_guc_ct *ct, > if (unlikely(desc->status)) > goto corrupted; > > - if (unlikely((tail | head) >= size)) { > +#ifdef CONFIG_DRM_I915_DEBUG_GUC > + if (unlikely((desc->tail | desc->head) >= size)) { > CT_ERROR(ct, "Invalid offsets head=%u tail=%u (size=%u)\n", > - head, tail, size); > + desc->head, desc->tail, size); > desc->status |= GUC_CTB_STATUS_OVERFLOW; > goto corrupted; nit: as we are now caching tail value, we can start comparing it with the value in descriptor and report GUC_CTB_STATUS_MISMATCH if needed > } > - > - /* > - * tail == head condition indicates empty. GuC FW does not support > - * using up the entire buffer to get tail == head meaning full. > - */ > - if (tail < head) > - used = (size - head) + tail; > - else > - used = tail - head; > - > - /* make sure there is a space including extra dw for the fence */ > - if (unlikely(used + len + 1 >= size)) > - return -ENOSPC; > +#endif > > /* >* dw0: CT header (including fence) > @@ -444,7 +435,9 @@ static int ct_write(struct intel_guc_ct *ct, > write_barrier(ct); > > /* now update descriptor */ > + ctb->tail = tail; > WRITE_ONCE(desc->tail, tail); > + ctb->space -= len + 1; > > return 0; > > @@ -460,7 +453,7 @@ static int ct_write(struct intel_guc_ct *ct, > * @req: pointer to pending request > * @status: placeholder for status > * > - * For each sent request, Guc shall send bac CT response message. > + * For each sent request, GuC shall send back CT response message. > * Our message handler will update status of tracked request once > * response message with given fence is received. Wait here and > * check for valid response status value. > @@ -508,24 +501,35 @@ static inline bool ct_deadlocked(struct intel_guc_ct > *ct) > return ret; > } > > -static inline bool ctb_has_room(struct intel_guc_ct_buffer *ctb, u32 len_dw) > +static inline bool h2g_has_room(struct intel_guc_ct *ct, u32 len_dw) this function was introduced moment ago ... can we minimize number of changes between patches ? > { > - struct guc_ct_buffer_desc *desc = ctb->desc; > - u32 head = READ_ONCE(desc->head); > + struct intel_guc_ct_buffer *ctb = &ct->ctbs.send; > + u32 head; > u32 space; > > - space = CIRC_SPACE(desc->tail, head, ctb->size); > + if (ctb->space >= len_dw) > + return true; > + > + head = READ_ONCE(ctb->desc->head); > + if (unlikely(head > ctb->size)) { > + CT_ERROR(ct, "Corrupted descriptor head=%u tail=%u size=%u\n", > + ctb->desc->head, ctb->desc->tail, ctb->size); > + ctb->desc->status |= GUC_CTB_STATUS_OVERFLOW; > + ctb->broken = true; > + return false; > + } > + > + space = CIRC_SPACE(ctb->tail, head, ctb->size); > + ctb->space = space; shouldn't we update our ctb->head with new head value? > > return space >= len_dw; > } > > static int has_room_nb(struct intel_guc_ct *ct, u32 len_dw) >
Re: [Intel-gfx] [RFC PATCH 39/97] drm/i915/guc: Increase size of CTB buffers
On 06.05.2021 21:13, Matthew Brost wrote: > With the introduction of non-blocking CTBs more than one CTB can be in > flight at a time. Increasing the size of the CTBs should reduce how > often software hits the case where no space is available in the CTB > buffer. > > Cc: John Harrison > Signed-off-by: Matthew Brost > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 11 --- > 1 file changed, 8 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > index 77dfbc94dcc3..d6895d29ed2d 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > @@ -63,11 +63,16 @@ static inline struct drm_device *ct_to_drm(struct > intel_guc_ct *ct) > * ++---+--+ > * > * Size of each `CT Buffer`_ must be multiple of 4K. > - * As we don't expect too many messages, for now use minimum sizes. > + * We don't expect too many messages in flight at any time, unless we are > + * using the GuC submission. In that case each request requires a minimum > + * 16 bytes which gives us a maximum 256 queue'd requests. Hopefully this nit: all our CTB calculations are in dwords now, not bytes > + * enough space to avoid backpressure on the driver. We increase the size > + * of the receive buffer (relative to the send) to ensure a G2H response > + * CTB has a landing spot. hmm, but we are not checking G2H CTB yet will start doing it around patch 54/97 so maybe this other patch should be introduced earlier ? > */ > #define CTB_DESC_SIZEALIGN(sizeof(struct > guc_ct_buffer_desc), SZ_2K) > #define CTB_H2G_BUFFER_SIZE (SZ_4K) > -#define CTB_G2H_BUFFER_SIZE (SZ_4K) > +#define CTB_G2H_BUFFER_SIZE (4 * CTB_H2G_BUFFER_SIZE) in theory, we (host) should be faster than GuC, so G2H CTB shall be almost always empty, if this is not a case, maybe we should start monitoring what is happening and report some warnings if G2H is half full ? > > #define MAX_US_STALL_CTB 100 > > @@ -753,7 +758,7 @@ static int ct_read(struct intel_guc_ct *ct, struct > ct_incoming_msg **msg) > /* beware of buffer wrap case */ > if (unlikely(available < 0)) > available += size; > - CT_DEBUG(ct, "available %d (%u:%u)\n", available, head, tail); > + CT_DEBUG(ct, "available %d (%u:%u:%u)\n", available, head, tail, size); > GEM_BUG_ON(available < 0); > > header = cmds[head]; >
Re: [RFC PATCH 40/97] drm/i915/guc: Module load failure test for CT buffer creation
On 06.05.2021 21:13, Matthew Brost wrote: > From: John Harrison > > Add several module failure load inject points in the CT buffer creation > code path. > > Signed-off-by: John Harrison > Signed-off-by: Matthew Brost > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 8 > 1 file changed, 8 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > index d6895d29ed2d..586e6efc3558 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > @@ -177,6 +177,10 @@ static int ct_register_buffer(struct intel_guc_ct *ct, > u32 type, > { > int err; > > + err = i915_inject_probe_error(guc_to_gt(ct_to_guc(ct))->i915, -ENXIO); > + if (unlikely(err)) > + return err; > + > err = guc_action_register_ct_buffer(ct_to_guc(ct), type, > desc_addr, buff_addr, size); > if (unlikely(err)) > @@ -228,6 +232,10 @@ int intel_guc_ct_init(struct intel_guc_ct *ct) > u32 *cmds; > int err; > > + err = i915_inject_probe_error(guc_to_gt(guc)->i915, -ENXIO); > + if (err) > + return err; > + > GEM_BUG_ON(ct->vma); > > blob_size = 2 * CTB_DESC_SIZE + CTB_H2G_BUFFER_SIZE + > CTB_G2H_BUFFER_SIZE; > likely could be introduced earlier, maybe right after patch 5/97 Reviewed-by: Michal Wajdeczko
Re: [Intel-gfx] [RFC PATCH 11/97] drm/i915/guc: Only rely on own CTB size
On 25.05.2021 04:47, Matthew Brost wrote: > On Thu, May 06, 2021 at 12:13:25PM -0700, Matthew Brost wrote: >> From: Michal Wajdeczko >> >> In upcoming GuC firmware, CTB size will be removed from the CTB >> descriptor so we must keep it locally for any calculations. >> >> While around, improve some debug messages and helpers. >> > > desc->size is still used in the patch and really shouldn't be per this goal of this patch was to start using local ctb->size for any calculations, not to drop it completely, as at this point (GuC 49) desc->size is still part of the CTB protocol > comment but a patch later in the series drops it. Seeing as this patch > and that patch are going to squashed into a single patch upgrading the > GuC firmware I think that is ok. no need to squash this patch in fact all CTB patches up to and including 20/97 ("drm/i915/guc: Introduce unified HXG messages") are compatible with current GuC 49.0.1 and IMHO *should* be merged separately only patches from 21/97 ("drm/i915/guc: Update MMIO based communication") to 29/97 ("drm/i915/guc: Update firmware to v60.1.2") must be squashed during merge, as this is were communication protocol is changing (from GuC 49 to GuC 60) and we may break existing functionality (HuC authentication) Michal > > With that: > Reviewed-by: Matthew Brost > >> Signed-off-by: Michal Wajdeczko >> Signed-off-by: Matthew Brost >> --- >> drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 55 +-- >> drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h | 2 + >> 2 files changed, 43 insertions(+), 14 deletions(-) >> >> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> index 4cc8c0b71699..dbece569fbe4 100644 >> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> @@ -90,6 +90,24 @@ static void guc_ct_buffer_desc_init(struct >> guc_ct_buffer_desc *desc, >> desc->owner = CTB_OWNER_HOST; >> } >> >> +static void guc_ct_buffer_reset(struct intel_guc_ct_buffer *ctb, u32 >> cmds_addr) >> +{ >> +guc_ct_buffer_desc_init(ctb->desc, cmds_addr, ctb->size); >> +} >> + >> +static void guc_ct_buffer_init(struct intel_guc_ct_buffer *ctb, >> + struct guc_ct_buffer_desc *desc, >> + u32 *cmds, u32 size) >> +{ >> +GEM_BUG_ON(size % 4); >> + >> +ctb->desc = desc; >> +ctb->cmds = cmds; >> +ctb->size = size; >> + >> +guc_ct_buffer_reset(ctb, 0); >> +} >> + >> static int guc_action_register_ct_buffer(struct intel_guc *guc, >> u32 desc_addr, >> u32 type) >> @@ -148,7 +166,10 @@ static int ct_deregister_buffer(struct intel_guc_ct >> *ct, u32 type) >> int intel_guc_ct_init(struct intel_guc_ct *ct) >> { >> struct intel_guc *guc = ct_to_guc(ct); >> +struct guc_ct_buffer_desc *desc; >> +u32 blob_size; >> void *blob; >> +u32 *cmds; >> int err; >> int i; >> >> @@ -176,19 +197,24 @@ int intel_guc_ct_init(struct intel_guc_ct *ct) >> * other code will need updating as well. >> */ >> >> -err = intel_guc_allocate_and_map_vma(guc, PAGE_SIZE, &ct->vma, &blob); >> +blob_size = PAGE_SIZE; >> +err = intel_guc_allocate_and_map_vma(guc, blob_size, &ct->vma, &blob); >> if (unlikely(err)) { >> -CT_ERROR(ct, "Failed to allocate CT channel (err=%d)\n", err); >> +CT_PROBE_ERROR(ct, "Failed to allocate %u for CTB data (%pe)\n", >> + blob_size, ERR_PTR(err)); >> return err; >> } >> >> -CT_DEBUG(ct, "vma base=%#x\n", intel_guc_ggtt_offset(guc, ct->vma)); >> +CT_DEBUG(ct, "base=%#x size=%u\n", intel_guc_ggtt_offset(guc, ct->vma), >> blob_size); >> >> /* store pointers to desc and cmds */ >> for (i = 0; i < ARRAY_SIZE(ct->ctbs); i++) { >> GEM_BUG_ON((i != CTB_SEND) && (i != CTB_RECV)); >> -ct->ctbs[i].desc = blob + PAGE_SIZE/4 * i; >> -ct->ctbs[i].cmds = blob + PAGE_SIZE/4 * i + PAGE_SIZE/2; >> + >> +desc = blob + PAGE_SIZE / 4 * i; >> +cmds = blob + PAGE_SIZE / 4 * i + PAGE_SIZE / 2; >> + >> +guc_ct_buffer_init(&ct->ctbs[i],
Re: [RFC PATCH 12/97] drm/i915/guc: Don't repeat CTB layout calculations
On 25.05.2021 04:53, Matthew Brost wrote: > On Thu, May 06, 2021 at 12:13:26PM -0700, Matthew Brost wrote: >> From: Michal Wajdeczko >> >> We can retrieve offsets to cmds buffers and descriptor from >> actual pointers that we already keep locally. >> >> Signed-off-by: Michal Wajdeczko >> Signed-off-by: Matthew Brost >> --- >> drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 16 ++-- >> 1 file changed, 10 insertions(+), 6 deletions(-) >> >> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> index dbece569fbe4..fbd6bd20f588 100644 >> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c >> @@ -244,6 +244,7 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct) >> { >> struct intel_guc *guc = ct_to_guc(ct); >> u32 base, cmds; >> +void *blob; >> int err; >> int i; >> >> @@ -251,15 +252,18 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct) >> >> /* vma should be already allocated and map'ed */ >> GEM_BUG_ON(!ct->vma); >> +GEM_BUG_ON(!i915_gem_object_has_pinned_pages(ct->vma->obj)); > > This doesn't really have anything to do with this patch, but again this > patch will be squashed into a large patch updating the GuC firmware, so > I think this is fine. again, no need to squash GuC patches up to 20/97 > > With that: > Reviewed-by: Matthew Brost > >> base = intel_guc_ggtt_offset(guc, ct->vma); >> >> -/* (re)initialize descriptors >> - * cmds buffers are in the second half of the blob page >> - */ >> +/* blob should start with send descriptor */ >> +blob = __px_vaddr(ct->vma->obj); >> +GEM_BUG_ON(blob != ct->ctbs[CTB_SEND].desc); >> + >> +/* (re)initialize descriptors */ >> for (i = 0; i < ARRAY_SIZE(ct->ctbs); i++) { >> GEM_BUG_ON((i != CTB_SEND) && (i != CTB_RECV)); >> >> -cmds = base + PAGE_SIZE / 4 * i + PAGE_SIZE / 2; >> +cmds = base + ptrdiff(ct->ctbs[i].cmds, blob); >> CT_DEBUG(ct, "%d: cmds addr=%#x\n", i, cmds); >> >> guc_ct_buffer_reset(&ct->ctbs[i], cmds); >> @@ -269,12 +273,12 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct) >> * Register both CT buffers starting with RECV buffer. >> * Descriptors are in first half of the blob. >> */ >> -err = ct_register_buffer(ct, base + PAGE_SIZE / 4 * CTB_RECV, >> +err = ct_register_buffer(ct, base + ptrdiff(ct->ctbs[CTB_RECV].desc, >> blob), >> INTEL_GUC_CT_BUFFER_TYPE_RECV); >> if (unlikely(err)) >> goto err_out; >> >> -err = ct_register_buffer(ct, base + PAGE_SIZE / 4 * CTB_SEND, >> +err = ct_register_buffer(ct, base + ptrdiff(ct->ctbs[CTB_SEND].desc, >> blob), >> INTEL_GUC_CT_BUFFER_TYPE_SEND); >> if (unlikely(err)) >> goto err_deregister; >> -- >> 2.28.0 >>