Expose the GL2 high-temporal residency threshold (GL2C_RESIDENCY_CTRL.REG_THRESHOLD) through a new per-device debugfs file, /sys/kernel/debug/dri/*/amdgpu_gl2_ht_threshold.
A read returns the current threshold as a decimal number; a write parses a decimal value and range-checks it against the field width. The get/set logic is implemented as gfx_funcs callbacks in gfx_v12_1, so the file is only created on ASICs that support the feature (GC IP >= 12.1.0). Signed-off-by: Alex Sierra <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 92 +++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h | 12 +++ drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c | 51 ++++++++++++ 4 files changed, 156 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index eb04583357df..6c2e39de7bb2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -2216,6 +2216,7 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev) amdgpu_debugfs_jpeg_sched_mask_init(adev); amdgpu_debugfs_gfx_sched_mask_init(adev); amdgpu_debugfs_compute_sched_mask_init(adev); + amdgpu_debugfs_gl2_ht_threshold_init(adev); amdgpu_debugfs_sdma_sched_mask_init(adev); amdgpu_ras_debugfs_create_all(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 1bbb3d646cfe..1047339295e7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -3327,6 +3327,98 @@ void amdgpu_debugfs_compute_sched_mask_init(struct amdgpu_device *adev) #endif } +/* + * debugfs to read/write the GL2 high-temporal residency threshold + * (GL2C_RESIDENCY_CTRL.REG_THRESHOLD). The value is expressed as a decimal + * number; writes are range-checked by the ASIC set() callback. + */ +#if defined(CONFIG_DEBUG_FS) +static int amdgpu_debugfs_gl2_ht_threshold_get(void *data, u64 *val) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)data; + u32 threshold = 0; + int r; + + if (!adev) + return -ENODEV; + if (!adev->gfx.funcs || !adev->gfx.funcs->get_gl2_ht_threshold) + return -EOPNOTSUPP; + /* Only SPX/DPX partition modes support GL2 residency control. */ + if (!amdgpu_gfx_gl2_residency_mode_supported(adev)) + return -EOPNOTSUPP; + + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); + if (r < 0) { + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + return r; + } + + r = adev->gfx.funcs->get_gl2_ht_threshold(adev, &threshold); + + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + + if (r) + return r; + + *val = threshold; + return 0; +} + +static int amdgpu_debugfs_gl2_ht_threshold_set(void *data, u64 val) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)data; + int r; + + if (!adev) + return -ENODEV; + if (!adev->gfx.funcs || !adev->gfx.funcs->set_gl2_ht_threshold) + return -EOPNOTSUPP; + /* Only SPX/DPX partition modes support GL2 residency control. */ + if (!amdgpu_gfx_gl2_residency_mode_supported(adev)) + return -EOPNOTSUPP; + if (val > U32_MAX) + return -EINVAL; + + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); + if (r < 0) { + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + return r; + } + + r = adev->gfx.funcs->set_gl2_ht_threshold(adev, (u32)val); + + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + + return r; +} + +DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_debugfs_gl2_ht_threshold_fops, + amdgpu_debugfs_gl2_ht_threshold_get, + amdgpu_debugfs_gl2_ht_threshold_set, "%llu\n"); + +#endif + +void amdgpu_debugfs_gl2_ht_threshold_init(struct amdgpu_device *adev) +{ +#if defined(CONFIG_DEBUG_FS) + struct drm_minor *minor = adev_to_drm(adev)->primary; + struct dentry *root = minor->debugfs_root; + + /* + * Only expose the file on ASICs that implement the GL2 HT threshold + * control. This is currently gfx12.1+ (GC IP >= 12.1.0). + */ + if (!adev->gfx.funcs || !adev->gfx.funcs->get_gl2_ht_threshold || + !adev->gfx.funcs->set_gl2_ht_threshold) + return; + + debugfs_create_file("amdgpu_gl2_ht_threshold", 0600, root, adev, + &amdgpu_debugfs_gl2_ht_threshold_fops); +#endif +} + int amdgpu_gfx_ring_preempt_ib(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h index 1b01dacddd25..34db5e7e4165 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h @@ -398,6 +398,12 @@ struct amdgpu_gfx_funcs { * persisting GL2 cache is accounted and programmed. SOC-specific. */ u32 (*get_num_gl2_instances)(struct amdgpu_device *adev); + /* Get/set the GL2 high-temporal residency threshold + * (GL2C_RESIDENCY_CTRL.REG_THRESHOLD). Only implemented on ASICs that + * support the feature; used to expose it through debugfs. + */ + int (*get_gl2_ht_threshold)(struct amdgpu_device *adev, u32 *val); + int (*set_gl2_ht_threshold)(struct amdgpu_device *adev, u32 val); }; struct sq_work { @@ -607,6 +613,11 @@ struct amdgpu_gfx { /* Persisting GL2 cache request accounting (gfx12.1+) */ struct amdgpu_gl2_persisting_mgr gl2_persisting; + + /* Placeholder software shadow of GL2C_RESIDENCY_CTRL.REG_THRESHOLD + * until the real register access is wired up (gfx12.1+). + */ + u32 gl2_ht_threshold; }; struct amdgpu_gfx_deferred_entry { @@ -755,6 +766,7 @@ void amdgpu_gfx_csb_preamble_end(u32 *buffer, u32 count); void amdgpu_debugfs_gfx_sched_mask_init(struct amdgpu_device *adev); void amdgpu_debugfs_compute_sched_mask_init(struct amdgpu_device *adev); +void amdgpu_debugfs_gl2_ht_threshold_init(struct amdgpu_device *adev); int amdgpu_gfx_ring_preempt_ib(struct amdgpu_ring *ring); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c index c3a165ca5998..7efd4f2e26eb 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c @@ -56,6 +56,13 @@ #define GL2C_RESIDENCY_CTRL__RESIDENCY_WAYS__SHIFT 0x0 #define GL2C_RESIDENCY_CTRL__RESIDENCY_WAYS_MASK 0x0000000FL +#define GL2C_RESIDENCY_CTRL__REG_THRESHOLD__SHIFT 0x4 +#define GL2C_RESIDENCY_CTRL__REG_THRESHOLD_MASK 0x000003F0L + +#define GL2C_RESIDENCY_THRESHOLD_MAX \ + (GL2C_RESIDENCY_CTRL__REG_THRESHOLD_MASK >> \ + GL2C_RESIDENCY_CTRL__REG_THRESHOLD__SHIFT) + #define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L #define regCP_HQD_EOP_CONTROL_DEFAULT 0x00000000 @@ -782,6 +789,48 @@ static u32 gfx_v12_1_get_num_gl2_instances(struct amdgpu_device *adev) return hweight32(adev->aid_mask); } +/* + * Read back the current GL2 high-temporal residency threshold + * (GL2C_RESIDENCY_CTRL.REG_THRESHOLD). + */ +static int gfx_v12_1_get_gl2_ht_threshold(struct amdgpu_device *adev, u32 *val) +{ + *val = adev->gfx.gl2_ht_threshold; + + dev_info(adev->dev, + "GL2 HT threshold read (placeholder): REG_THRESHOLD=%u\n", + *val); + + return 0; +} + +/* + * Program the GL2 high-temporal residency threshold + * (GL2C_RESIDENCY_CTRL.REG_THRESHOLD). + * + */ +static int gfx_v12_1_set_gl2_ht_threshold(struct amdgpu_device *adev, u32 val) +{ + /* + * REG_THRESHOLD is a PF-only register. As with RESIDENCY_WAYS it must + * never be programmed by a guest in multi-VF mode, where it would + * disturb the shared GL2 policy of the other VFs. + */ + if (amdgpu_sriov_multi_vf_mode(adev)) + return -EPERM; + + if (val > GL2C_RESIDENCY_THRESHOLD_MAX) + return -EINVAL; + + adev->gfx.gl2_ht_threshold = val; + + dev_info(adev->dev, + "GL2 HT threshold write (placeholder): REG_THRESHOLD=%u\n", + val); + + return 0; +} + static const struct amdgpu_gfx_funcs gfx_v12_1_gfx_funcs = { .get_gpu_clock_counter = &gfx_v12_1_get_gpu_clock_counter, .select_se_sh = &gfx_v12_1_xcc_select_se_sh, @@ -795,6 +844,8 @@ static const struct amdgpu_gfx_funcs gfx_v12_1_gfx_funcs = { .set_persisting_gl2_cache = &gfx_v12_1_set_persisting_gl2_cache, .xcc_to_gl2_instance_mask = &gfx_v12_1_xcc_to_gl2_instance_mask, .get_num_gl2_instances = &gfx_v12_1_get_num_gl2_instances, + .get_gl2_ht_threshold = &gfx_v12_1_get_gl2_ht_threshold, + .set_gl2_ht_threshold = &gfx_v12_1_set_gl2_ht_threshold, }; static int gfx_v12_1_gpu_early_init(struct amdgpu_device *adev) -- 2.34.1
