[Intel-gfx] [PATCH v3 1/4] drm/i915/guc: Add fetch of hwconfig table
Michal Wajdeczko
michal.wajdeczko at intel.com
Tue Feb 8 21:56:28 UTC 2022
On 08.02.2022 22:05, Jordan Justen wrote:
> From: John Harrison <John.C.Harrison at Intel.com>
>
> 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 <michal.wajdeczko at intel.com>
> Signed-off-by: Rodrigo Vivi <rodrigo.vivi at intel.com>
> Signed-off-by: John Harrison <John.C.Harrison at Intel.com>
> Reviewed-by: Matthew Brost <matthew.brost at intel.com>
> ---
> 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 000000000000..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 explicit "inline"
> +{
> + return container_of(hwconfig, struct intel_guc, hwconfig);
> +}
> +
> +/*
> + * GuC has a blob containing hardware configuration information (HWConfig).
> + * This is formatted as a simple and flexible KLV (Key/Length/Value) table.
> + *
> + * For example, a minimal version could be:
> + * enum device_attr {
> + * ATTR_SOME_VALUE = 0,
> + * ATTR_SOME_MASK = 1,
> + * };
> + *
> + * static const u32 hwconfig[] = {
> + * ATTR_SOME_VALUE,
> + * 1, // Value Length in DWords
> + * 8, // Value
> + *
> + * ATTR_SOME_MASK,
> + * 3,
> + * 0x00FFFFFFFF, 0xFFFFFFFF, 0xFF000000,
> + * };
> + *
> + * The attribute ids are defined in a hardware spec.
> + */
> +
> +static int __guc_action_get_hwconfig(struct intel_guc_hwconfig *hwconfig,
since this is "guc_action" then you should pass "guc" instead of
"hwconfig" (as you don't need anything from hwconfig in this helper)
> + u32 ggtt_offset, u32 ggtt_size)
> +{
> + struct intel_guc *guc = hwconfig_to_guc(hwconfig);
> + u32 action[] = {
> + INTEL_GUC_ACTION_GET_HWCONFIG,
> + ggtt_offset,
> + 0, /* upper 32 bits of address */
> + ggtt_size,
> + };
> + int ret;
> +
> + ret = intel_guc_send_mmio(guc, action, ARRAY_SIZE(action), NULL, 0);
> + if (ret == -ENXIO)
> + return -ENOENT;
> +
> + if (!ggtt_size && !ret)
> + ret = -EINVAL;
you have dedicated function for query/discover size, any special error
handling shall be done there
> +
> + return ret;
> +}
> +
> +static int guc_hwconfig_discover_size(struct intel_guc_hwconfig *hwconfig)
> +{
> + int ret;
> +
> + /* Sending a query with too small a table will return the size of the table */
sending too small buffer size should result in error
only passing zero offset/size is treated as a query
> + ret = __guc_action_get_hwconfig(hwconfig, 0, 0);
> + if (ret < 0)
> + return ret;
> +
> + hwconfig->size = ret;
> + return 0;
> +}
> +
> +static int guc_hwconfig_fill_buffer(struct intel_guc_hwconfig *hwconfig)
> +{
> + struct intel_guc *guc = hwconfig_to_guc(hwconfig);
> + struct i915_vma *vma;
> + u32 ggtt_offset;
> + void *vaddr;
> + int ret;
> +
> + GEM_BUG_ON(!hwconfig->size);
> +
> + ret = intel_guc_allocate_and_map_vma(guc, hwconfig->size, &vma, &vaddr);
> + if (ret)
> + return ret;
> +
> + ggtt_offset = intel_guc_ggtt_offset(guc, vma);
> +
> + ret = __guc_action_get_hwconfig(hwconfig, ggtt_offset, hwconfig->size);
> + if (ret >= 0)
> + memcpy(hwconfig->ptr, vaddr, hwconfig->size);
> +
> + i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP);
> +
> + return ret;
> +}
> +
> +static bool has_table(struct drm_i915_private *i915)
> +{
> + if (IS_ALDERLAKE_P(i915))
> + return true;
shouldn't this be a part of our device_info ?
func(has_gt_uc); \
func(has_guc_deprivilege); \
+ func(has_guc_hwconfig); \
> +
> + return false;
> +}
> +
> +/**
> + * intel_guc_hwconfig_fini - Finalize the HWConfig
> + *
> + * Free up the memory allocation holding the table.
> + */
> +void intel_guc_hwconfig_fini(struct intel_guc_hwconfig *hwconfig)
> +{
> + kfree(hwconfig->ptr);
> + hwconfig->size = 0;
> + hwconfig->ptr = NULL;
> +}
> +
> +/**
> + * intel_guc_hwconfig_init - Initialize the HWConfig
> + *
> + * Retrieve the HWConfig table from the GuC and save it away in a local memory
> + * allocation. It can then be queried on demand by other users later on.
> + */
> +int intel_guc_hwconfig_init(struct intel_guc_hwconfig *hwconfig)
> +{
> + struct intel_guc *guc = hwconfig_to_guc(hwconfig);
> + struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
> + int ret;
> +
> + if (!has_table(i915))
> + return 0;
> +
> + ret = guc_hwconfig_discover_size(hwconfig);
> + if (ret)
> + return ret;
> +
> + hwconfig->ptr = kmalloc(hwconfig->size, GFP_KERNEL);
> + if (!hwconfig->ptr) {
> + hwconfig->size = 0;
> + return -ENOMEM;
> + }
> +
> + ret = guc_hwconfig_fill_buffer(hwconfig);
> + if (ret < 0) {
> + intel_guc_hwconfig_fini(hwconfig);
> + return ret;
> + }
> +
> + return 0;
> +}
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.h
> new file mode 100644
> index 000000000000..fdd7f0d6e938
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.h
> @@ -0,0 +1,19 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2021 Intel Corporation
2022
> + */
> +
> +#ifndef _INTEL_GUC_HWCONFIG_H_
> +#define _INTEL_GUC_HWCONFIG_H_
> +
> +#include <linux/types.h>
> +
> +struct intel_guc_hwconfig {
> + u32 size;
> + void *ptr;
> +};
> +
> +int intel_guc_hwconfig_init(struct intel_guc_hwconfig *hwconfig);
> +void intel_guc_hwconfig_fini(struct intel_guc_hwconfig *hwconfig);
> +
> +#endif /* _INTEL_GUC_HWCONFIG_H_ */
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
> index 09ed29df67bc..d045ff6d4d63 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
> @@ -489,6 +489,10 @@ static int __uc_init_hw(struct intel_uc *uc)
> if (ret)
> goto err_log_capture;
>
> + ret = intel_guc_hwconfig_init(&guc->hwconfig);
> + if (ret)
> + drm_err(&i915->drm, "Failed to retrieve hwconfig table: %d\n", ret);
maybe drm_notice since we continue probe
nit: you may report error as: "%pe", ERR_PTR(ret)
Michal
> +
> ret = guc_enable_communication(guc);
> if (ret)
> goto err_log_capture;
> @@ -562,6 +566,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);
> }
>
More information about the Intel-gfx
mailing list