-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
drm/i915/guc: Add fetch of hwconfig blob
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. The table is stored in the GT structure so that it can be fetched once at driver load time. Keeping inside a GuC structure would mean it would be release and reloaded on a GuC reset (part of a full GT reset). However, the table does not change just because the GT has been reset and the GuC reloaded. Also, dynamic memory allocations inside the reset path are a problem. Note that the table is only available on ADL-P and later platforms. v2 (John's v2 patch): * Move to GT level to avoid memory allocation during reset path (and unnecessary re-read of the table on a reset). 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 v6 (of Jordan's posting): * Added a couple more small changes recommended by Michal * Merge in John's v2 patch, but note: - Using drm_notice as recommended by Michal - Reverted Michal's suggestion of using devinfo v7 (of Jordan's posting): * Change back to drm_err as preferred by John Cc: Michal Wajdeczko <michal.wajdeczko@intel.com> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: John Harrison <John.C.Harrison@Intel.com> Reviewed-by: Matthew Brost <matthew.brost@intel.com> Acked-by: Jon Bloomfield <jon.bloomfield@intel.com> Signed-off-by: Jordan Justen <jordan.l.justen@intel.com> Reviewed-by: Michal Wajdeczko <michal.wajdeczko@intel.com> Signed-off-by: John Harrison <John.C.Harrison@Intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220306232157.1174335-2-jordan.l.justen@intel.com
- Loading branch information
John Harrison
authored and
John Harrison
committed
Mar 18, 2022
1 parent
7fe7c2a
commit 8781f05
Showing
7 changed files
with
199 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/* SPDX-License-Identifier: MIT */ | ||
/* | ||
* Copyright © 2022 Intel Corporation | ||
*/ | ||
|
||
#ifndef _INTEL_HWCONFIG_H_ | ||
#define _INTEL_HWCONFIG_H_ | ||
|
||
#include <linux/types.h> | ||
|
||
struct intel_gt; | ||
|
||
struct intel_hwconfig { | ||
u32 size; | ||
void *ptr; | ||
}; | ||
|
||
int intel_gt_init_hwconfig(struct intel_gt *gt); | ||
void intel_gt_fini_hwconfig(struct intel_gt *gt); | ||
|
||
#endif /* _INTEL_HWCONFIG_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
// SPDX-License-Identifier: MIT | ||
/* | ||
* Copyright © 2022 Intel Corporation | ||
*/ | ||
|
||
#include "gt/intel_gt.h" | ||
#include "gt/intel_hwconfig.h" | ||
#include "i915_drv.h" | ||
#include "i915_memcpy.h" | ||
|
||
/* | ||
* 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 *guc, | ||
u32 ggtt_offset, u32 ggtt_size) | ||
{ | ||
u32 action[] = { | ||
INTEL_GUC_ACTION_GET_HWCONFIG, | ||
lower_32_bits(ggtt_offset), | ||
upper_32_bits(ggtt_offset), | ||
ggtt_size, | ||
}; | ||
int ret; | ||
|
||
ret = intel_guc_send_mmio(guc, action, ARRAY_SIZE(action), NULL, 0); | ||
if (ret == -ENXIO) | ||
return -ENOENT; | ||
|
||
return ret; | ||
} | ||
|
||
static int guc_hwconfig_discover_size(struct intel_guc *guc, struct intel_hwconfig *hwconfig) | ||
{ | ||
int ret; | ||
|
||
/* | ||
* Sending a query with zero offset and size will return the | ||
* size of the blob. | ||
*/ | ||
ret = __guc_action_get_hwconfig(guc, 0, 0); | ||
if (ret < 0) | ||
return ret; | ||
|
||
if (ret == 0) | ||
return -EINVAL; | ||
|
||
hwconfig->size = ret; | ||
return 0; | ||
} | ||
|
||
static int guc_hwconfig_fill_buffer(struct intel_guc *guc, struct intel_hwconfig *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(guc, 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; | ||
|
||
return false; | ||
} | ||
|
||
/** | ||
* intel_guc_hwconfig_init - Initialize the HWConfig | ||
* | ||
* Retrieve the HWConfig table from the GuC and save it locally. | ||
* It can then be queried on demand by other users later on. | ||
*/ | ||
static int guc_hwconfig_init(struct intel_gt *gt) | ||
{ | ||
struct intel_hwconfig *hwconfig = >->info.hwconfig; | ||
struct intel_guc *guc = >->uc.guc; | ||
int ret; | ||
|
||
if (!has_table(gt->i915)) | ||
return 0; | ||
|
||
ret = guc_hwconfig_discover_size(guc, 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(guc, hwconfig); | ||
if (ret < 0) { | ||
intel_gt_fini_hwconfig(gt); | ||
return ret; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
/** | ||
* intel_gt_init_hwconfig - Initialize the HWConfig if available | ||
* | ||
* Retrieve the HWConfig table if available on the current platform. | ||
*/ | ||
int intel_gt_init_hwconfig(struct intel_gt *gt) | ||
{ | ||
if (!intel_uc_uses_guc(>->uc)) | ||
return 0; | ||
|
||
return guc_hwconfig_init(gt); | ||
} | ||
|
||
/** | ||
* intel_gt_fini_hwconfig - Finalize the HWConfig | ||
* | ||
* Free up the memory allocation holding the table. | ||
*/ | ||
void intel_gt_fini_hwconfig(struct intel_gt *gt) | ||
{ | ||
struct intel_hwconfig *hwconfig = >->info.hwconfig; | ||
|
||
kfree(hwconfig->ptr); | ||
hwconfig->size = 0; | ||
hwconfig->ptr = NULL; | ||
} |