mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-30 00:03:27 -04:00
Merge tag 'amd-drm-fixes-7.0-2026-03-25' of https://gitlab.freedesktop.org/agd5f/linux into drm-fixes
amd-drm-fixes-7.0-2026-03-25: amdgpu: - DSC fix - Module parameter parsing fix - PASID reuse fix - drm_edid leak fix - SMU 13.x fixes - SMU 14.x fix - Fence fix in amdgpu_amdkfd_submit_ib() - LVDS fixes - GPU page fault fix for non-4K pages amdkfd: - Ordering fix in kfd_ioctl_create_process() Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patch.msgid.link/20260325155600.4184877-1-alexander.deucher@amd.com
This commit is contained in:
@@ -692,9 +692,9 @@ int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
|
||||
goto err_ib_sched;
|
||||
}
|
||||
|
||||
/* Drop the initial kref_init count (see drm_sched_main as example) */
|
||||
dma_fence_put(f);
|
||||
ret = dma_fence_wait(f, false);
|
||||
/* Drop the returned fence reference after the wait completes */
|
||||
dma_fence_put(f);
|
||||
|
||||
err_ib_sched:
|
||||
amdgpu_job_free(job);
|
||||
|
||||
@@ -4207,7 +4207,8 @@ static void amdgpu_device_xgmi_reset_func(struct work_struct *__work)
|
||||
|
||||
static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev)
|
||||
{
|
||||
char *input = amdgpu_lockup_timeout;
|
||||
char buf[AMDGPU_MAX_TIMEOUT_PARAM_LENGTH];
|
||||
char *input = buf;
|
||||
char *timeout_setting = NULL;
|
||||
int index = 0;
|
||||
long timeout;
|
||||
@@ -4217,9 +4218,17 @@ static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev)
|
||||
adev->gfx_timeout = adev->compute_timeout = adev->sdma_timeout =
|
||||
adev->video_timeout = msecs_to_jiffies(2000);
|
||||
|
||||
if (!strnlen(input, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH))
|
||||
if (!strnlen(amdgpu_lockup_timeout, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* strsep() destructively modifies its input by replacing delimiters
|
||||
* with '\0'. Use a stack copy so the global module parameter buffer
|
||||
* remains intact for multi-GPU systems where this function is called
|
||||
* once per device.
|
||||
*/
|
||||
strscpy(buf, amdgpu_lockup_timeout, sizeof(buf));
|
||||
|
||||
while ((timeout_setting = strsep(&input, ",")) &&
|
||||
strnlen(timeout_setting, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH)) {
|
||||
ret = kstrtol(timeout_setting, 0, &timeout);
|
||||
|
||||
@@ -35,10 +35,13 @@
|
||||
* PASIDs are global address space identifiers that can be shared
|
||||
* between the GPU, an IOMMU and the driver. VMs on different devices
|
||||
* may use the same PASID if they share the same address
|
||||
* space. Therefore PASIDs are allocated using a global IDA. VMs are
|
||||
* looked up from the PASID per amdgpu_device.
|
||||
* space. Therefore PASIDs are allocated using IDR cyclic allocator
|
||||
* (similar to kernel PID allocation) which naturally delays reuse.
|
||||
* VMs are looked up from the PASID per amdgpu_device.
|
||||
*/
|
||||
static DEFINE_IDA(amdgpu_pasid_ida);
|
||||
|
||||
static DEFINE_IDR(amdgpu_pasid_idr);
|
||||
static DEFINE_SPINLOCK(amdgpu_pasid_idr_lock);
|
||||
|
||||
/* Helper to free pasid from a fence callback */
|
||||
struct amdgpu_pasid_cb {
|
||||
@@ -50,8 +53,8 @@ struct amdgpu_pasid_cb {
|
||||
* amdgpu_pasid_alloc - Allocate a PASID
|
||||
* @bits: Maximum width of the PASID in bits, must be at least 1
|
||||
*
|
||||
* Allocates a PASID of the given width while keeping smaller PASIDs
|
||||
* available if possible.
|
||||
* Uses kernel's IDR cyclic allocator (same as PID allocation).
|
||||
* Allocates sequentially with automatic wrap-around.
|
||||
*
|
||||
* Returns a positive integer on success. Returns %-EINVAL if bits==0.
|
||||
* Returns %-ENOSPC if no PASID was available. Returns %-ENOMEM on
|
||||
@@ -59,14 +62,15 @@ struct amdgpu_pasid_cb {
|
||||
*/
|
||||
int amdgpu_pasid_alloc(unsigned int bits)
|
||||
{
|
||||
int pasid = -EINVAL;
|
||||
int pasid;
|
||||
|
||||
for (bits = min(bits, 31U); bits > 0; bits--) {
|
||||
pasid = ida_alloc_range(&amdgpu_pasid_ida, 1U << (bits - 1),
|
||||
(1U << bits) - 1, GFP_KERNEL);
|
||||
if (pasid != -ENOSPC)
|
||||
break;
|
||||
}
|
||||
if (bits == 0)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&amdgpu_pasid_idr_lock);
|
||||
pasid = idr_alloc_cyclic(&amdgpu_pasid_idr, NULL, 1,
|
||||
1U << bits, GFP_KERNEL);
|
||||
spin_unlock(&amdgpu_pasid_idr_lock);
|
||||
|
||||
if (pasid >= 0)
|
||||
trace_amdgpu_pasid_allocated(pasid);
|
||||
@@ -81,7 +85,10 @@ int amdgpu_pasid_alloc(unsigned int bits)
|
||||
void amdgpu_pasid_free(u32 pasid)
|
||||
{
|
||||
trace_amdgpu_pasid_freed(pasid);
|
||||
ida_free(&amdgpu_pasid_ida, pasid);
|
||||
|
||||
spin_lock(&amdgpu_pasid_idr_lock);
|
||||
idr_remove(&amdgpu_pasid_idr, pasid);
|
||||
spin_unlock(&amdgpu_pasid_idr_lock);
|
||||
}
|
||||
|
||||
static void amdgpu_pasid_free_cb(struct dma_fence *fence,
|
||||
@@ -616,3 +623,15 @@ void amdgpu_vmid_mgr_fini(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_pasid_mgr_cleanup - cleanup PASID manager
|
||||
*
|
||||
* Cleanup the IDR allocator.
|
||||
*/
|
||||
void amdgpu_pasid_mgr_cleanup(void)
|
||||
{
|
||||
spin_lock(&amdgpu_pasid_idr_lock);
|
||||
idr_destroy(&amdgpu_pasid_idr);
|
||||
spin_unlock(&amdgpu_pasid_idr_lock);
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ int amdgpu_pasid_alloc(unsigned int bits);
|
||||
void amdgpu_pasid_free(u32 pasid);
|
||||
void amdgpu_pasid_free_delayed(struct dma_resv *resv,
|
||||
u32 pasid);
|
||||
void amdgpu_pasid_mgr_cleanup(void);
|
||||
|
||||
bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev,
|
||||
struct amdgpu_vmid *id);
|
||||
|
||||
@@ -2898,6 +2898,7 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev)
|
||||
xa_destroy(&adev->vm_manager.pasids);
|
||||
|
||||
amdgpu_vmid_mgr_fini(adev);
|
||||
amdgpu_pasid_mgr_cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2973,14 +2974,14 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
|
||||
if (!root)
|
||||
return false;
|
||||
|
||||
addr /= AMDGPU_GPU_PAGE_SIZE;
|
||||
|
||||
if (is_compute_context && !svm_range_restore_pages(adev, pasid, vmid,
|
||||
node_id, addr, ts, write_fault)) {
|
||||
node_id, addr >> PAGE_SHIFT, ts, write_fault)) {
|
||||
amdgpu_bo_unref(&root);
|
||||
return true;
|
||||
}
|
||||
|
||||
addr /= AMDGPU_GPU_PAGE_SIZE;
|
||||
|
||||
r = amdgpu_bo_reserve(root, true);
|
||||
if (r)
|
||||
goto error_unref;
|
||||
|
||||
@@ -3170,11 +3170,11 @@ static int kfd_ioctl_create_process(struct file *filep, struct kfd_process *p, v
|
||||
struct kfd_process *process;
|
||||
int ret;
|
||||
|
||||
/* Each FD owns only one kfd_process */
|
||||
if (p->context_id != KFD_CONTEXT_ID_PRIMARY)
|
||||
if (!filep->private_data || !p)
|
||||
return -EINVAL;
|
||||
|
||||
if (!filep->private_data || !p)
|
||||
/* Each FD owns only one kfd_process */
|
||||
if (p->context_id != KFD_CONTEXT_ID_PRIMARY)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&kfd_processes_mutex);
|
||||
|
||||
@@ -3909,8 +3909,9 @@ void amdgpu_dm_update_connector_after_detect(
|
||||
|
||||
aconnector->dc_sink = sink;
|
||||
dc_sink_retain(aconnector->dc_sink);
|
||||
drm_edid_free(aconnector->drm_edid);
|
||||
aconnector->drm_edid = NULL;
|
||||
if (sink->dc_edid.length == 0) {
|
||||
aconnector->drm_edid = NULL;
|
||||
hdmi_cec_unset_edid(aconnector);
|
||||
if (aconnector->dc_link->aux_mode) {
|
||||
drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux);
|
||||
@@ -5422,7 +5423,7 @@ static void setup_backlight_device(struct amdgpu_display_manager *dm,
|
||||
caps = &dm->backlight_caps[aconnector->bl_idx];
|
||||
|
||||
/* Only offer ABM property when non-OLED and user didn't turn off by module parameter */
|
||||
if (!caps->ext_caps->bits.oled && amdgpu_dm_abm_level < 0)
|
||||
if (caps->ext_caps && !caps->ext_caps->bits.oled && amdgpu_dm_abm_level < 0)
|
||||
drm_object_attach_property(&aconnector->base.base,
|
||||
dm->adev->mode_info.abm_level_property,
|
||||
ABM_SYSFS_CONTROL);
|
||||
@@ -12523,6 +12524,11 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
||||
}
|
||||
|
||||
if (dc_resource_is_dsc_encoding_supported(dc)) {
|
||||
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
|
||||
dm_new_crtc_state->mode_changed_independent_from_dsc = new_crtc_state->mode_changed;
|
||||
}
|
||||
|
||||
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||
if (drm_atomic_crtc_needs_modeset(new_crtc_state)) {
|
||||
ret = add_affected_mst_dsc_crtcs(state, crtc);
|
||||
|
||||
@@ -984,6 +984,7 @@ struct dm_crtc_state {
|
||||
|
||||
bool freesync_vrr_info_changed;
|
||||
|
||||
bool mode_changed_independent_from_dsc;
|
||||
bool dsc_force_changed;
|
||||
bool vrr_supported;
|
||||
struct mod_freesync_config freesync_config;
|
||||
|
||||
@@ -1744,9 +1744,11 @@ int pre_validate_dsc(struct drm_atomic_state *state,
|
||||
int ind = find_crtc_index_in_state_by_stream(state, stream);
|
||||
|
||||
if (ind >= 0) {
|
||||
struct dm_crtc_state *dm_new_crtc_state = to_dm_crtc_state(state->crtcs[ind].new_state);
|
||||
|
||||
DRM_INFO_ONCE("%s:%d MST_DSC no mode changed for stream 0x%p\n",
|
||||
__func__, __LINE__, stream);
|
||||
state->crtcs[ind].new_state->mode_changed = 0;
|
||||
dm_new_crtc_state->base.mode_changed = dm_new_crtc_state->mode_changed_independent_from_dsc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -650,9 +650,6 @@ static struct link_encoder *dce100_link_encoder_create(
|
||||
return &enc110->base;
|
||||
}
|
||||
|
||||
if (enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
|
||||
return NULL;
|
||||
|
||||
link_regs_id =
|
||||
map_transmitter_id_to_phy_instance(enc_init_data->transmitter);
|
||||
|
||||
@@ -661,7 +658,8 @@ static struct link_encoder *dce100_link_encoder_create(
|
||||
&link_enc_feature,
|
||||
&link_enc_regs[link_regs_id],
|
||||
&link_enc_aux_regs[enc_init_data->channel - 1],
|
||||
&link_enc_hpd_regs[enc_init_data->hpd_source]);
|
||||
enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ?
|
||||
NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]);
|
||||
return &enc110->base;
|
||||
}
|
||||
|
||||
|
||||
@@ -671,7 +671,7 @@ static struct link_encoder *dce110_link_encoder_create(
|
||||
kzalloc_obj(struct dce110_link_encoder);
|
||||
int link_regs_id;
|
||||
|
||||
if (!enc110 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
|
||||
if (!enc110)
|
||||
return NULL;
|
||||
|
||||
link_regs_id =
|
||||
@@ -682,7 +682,8 @@ static struct link_encoder *dce110_link_encoder_create(
|
||||
&link_enc_feature,
|
||||
&link_enc_regs[link_regs_id],
|
||||
&link_enc_aux_regs[enc_init_data->channel - 1],
|
||||
&link_enc_hpd_regs[enc_init_data->hpd_source]);
|
||||
enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ?
|
||||
NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]);
|
||||
return &enc110->base;
|
||||
}
|
||||
|
||||
|
||||
@@ -632,7 +632,7 @@ static struct link_encoder *dce112_link_encoder_create(
|
||||
kzalloc_obj(struct dce110_link_encoder);
|
||||
int link_regs_id;
|
||||
|
||||
if (!enc110 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
|
||||
if (!enc110)
|
||||
return NULL;
|
||||
|
||||
link_regs_id =
|
||||
@@ -643,7 +643,8 @@ static struct link_encoder *dce112_link_encoder_create(
|
||||
&link_enc_feature,
|
||||
&link_enc_regs[link_regs_id],
|
||||
&link_enc_aux_regs[enc_init_data->channel - 1],
|
||||
&link_enc_hpd_regs[enc_init_data->hpd_source]);
|
||||
enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ?
|
||||
NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]);
|
||||
return &enc110->base;
|
||||
}
|
||||
|
||||
|
||||
@@ -716,7 +716,7 @@ static struct link_encoder *dce120_link_encoder_create(
|
||||
kzalloc_obj(struct dce110_link_encoder);
|
||||
int link_regs_id;
|
||||
|
||||
if (!enc110 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
|
||||
if (!enc110)
|
||||
return NULL;
|
||||
|
||||
link_regs_id =
|
||||
@@ -727,7 +727,8 @@ static struct link_encoder *dce120_link_encoder_create(
|
||||
&link_enc_feature,
|
||||
&link_enc_regs[link_regs_id],
|
||||
&link_enc_aux_regs[enc_init_data->channel - 1],
|
||||
&link_enc_hpd_regs[enc_init_data->hpd_source]);
|
||||
enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ?
|
||||
NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]);
|
||||
|
||||
return &enc110->base;
|
||||
}
|
||||
|
||||
@@ -746,18 +746,16 @@ static struct link_encoder *dce60_link_encoder_create(
|
||||
return &enc110->base;
|
||||
}
|
||||
|
||||
if (enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
|
||||
return NULL;
|
||||
|
||||
link_regs_id =
|
||||
map_transmitter_id_to_phy_instance(enc_init_data->transmitter);
|
||||
|
||||
dce60_link_encoder_construct(enc110,
|
||||
enc_init_data,
|
||||
&link_enc_feature,
|
||||
&link_enc_regs[link_regs_id],
|
||||
&link_enc_aux_regs[enc_init_data->channel - 1],
|
||||
&link_enc_hpd_regs[enc_init_data->hpd_source]);
|
||||
enc_init_data,
|
||||
&link_enc_feature,
|
||||
&link_enc_regs[link_regs_id],
|
||||
&link_enc_aux_regs[enc_init_data->channel - 1],
|
||||
enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ?
|
||||
NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]);
|
||||
return &enc110->base;
|
||||
}
|
||||
|
||||
|
||||
@@ -752,9 +752,6 @@ static struct link_encoder *dce80_link_encoder_create(
|
||||
return &enc110->base;
|
||||
}
|
||||
|
||||
if (enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
|
||||
return NULL;
|
||||
|
||||
link_regs_id =
|
||||
map_transmitter_id_to_phy_instance(enc_init_data->transmitter);
|
||||
|
||||
@@ -763,7 +760,8 @@ static struct link_encoder *dce80_link_encoder_create(
|
||||
&link_enc_feature,
|
||||
&link_enc_regs[link_regs_id],
|
||||
&link_enc_aux_regs[enc_init_data->channel - 1],
|
||||
&link_enc_hpd_regs[enc_init_data->hpd_source]);
|
||||
enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ?
|
||||
NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]);
|
||||
return &enc110->base;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,10 @@
|
||||
|
||||
#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
|
||||
|
||||
static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu,
|
||||
int od_feature_bit,
|
||||
int32_t *min, int32_t *max);
|
||||
|
||||
static const struct smu_feature_bits smu_v13_0_0_dpm_features = {
|
||||
.bits = {
|
||||
SMU_FEATURE_BIT_INIT(FEATURE_DPM_GFXCLK_BIT),
|
||||
@@ -1043,8 +1047,35 @@ static bool smu_v13_0_0_is_od_feature_supported(struct smu_context *smu,
|
||||
PPTable_t *pptable = smu->smu_table.driver_pptable;
|
||||
const OverDriveLimits_t * const overdrive_upperlimits =
|
||||
&pptable->SkuTable.OverDriveLimitsBasicMax;
|
||||
int32_t min_value, max_value;
|
||||
bool feature_enabled;
|
||||
|
||||
return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit);
|
||||
switch (od_feature_bit) {
|
||||
case PP_OD_FEATURE_FAN_CURVE_BIT:
|
||||
feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
|
||||
if (feature_enabled) {
|
||||
smu_v13_0_0_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_TEMP,
|
||||
&min_value, &max_value);
|
||||
if (!min_value && !max_value) {
|
||||
feature_enabled = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
smu_v13_0_0_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_PWM,
|
||||
&min_value, &max_value);
|
||||
if (!min_value && !max_value) {
|
||||
feature_enabled = false;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
return feature_enabled;
|
||||
}
|
||||
|
||||
static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu,
|
||||
|
||||
@@ -1391,7 +1391,7 @@ static int smu_v13_0_6_emit_clk_levels(struct smu_context *smu,
|
||||
break;
|
||||
case SMU_OD_MCLK:
|
||||
if (!smu_v13_0_6_cap_supported(smu, SMU_CAP(SET_UCLK_MAX)))
|
||||
return 0;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
size += sysfs_emit_at(buf, size, "%s:\n", "OD_MCLK");
|
||||
size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
|
||||
@@ -2122,6 +2122,7 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu,
|
||||
{
|
||||
struct smu_dpm_context *smu_dpm = &(smu->smu_dpm);
|
||||
struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
|
||||
struct smu_dpm_table *uclk_table = &dpm_context->dpm_tables.uclk_table;
|
||||
struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
|
||||
uint32_t min_clk;
|
||||
uint32_t max_clk;
|
||||
@@ -2221,14 +2222,16 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
min_clk = SMU_DPM_TABLE_MIN(
|
||||
&dpm_context->dpm_tables.uclk_table);
|
||||
max_clk = SMU_DPM_TABLE_MAX(
|
||||
&dpm_context->dpm_tables.uclk_table);
|
||||
ret = smu_v13_0_6_set_soft_freq_limited_range(
|
||||
smu, SMU_UCLK, min_clk, max_clk, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (SMU_DPM_TABLE_MAX(uclk_table) !=
|
||||
pstate_table->uclk_pstate.curr.max) {
|
||||
min_clk = SMU_DPM_TABLE_MIN(&dpm_context->dpm_tables.uclk_table);
|
||||
max_clk = SMU_DPM_TABLE_MAX(&dpm_context->dpm_tables.uclk_table);
|
||||
ret = smu_v13_0_6_set_soft_freq_limited_range(smu,
|
||||
SMU_UCLK, min_clk,
|
||||
max_clk, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
smu_v13_0_reset_custom_level(smu);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -59,6 +59,10 @@
|
||||
|
||||
#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
|
||||
|
||||
static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
|
||||
int od_feature_bit,
|
||||
int32_t *min, int32_t *max);
|
||||
|
||||
static const struct smu_feature_bits smu_v13_0_7_dpm_features = {
|
||||
.bits = {
|
||||
SMU_FEATURE_BIT_INIT(FEATURE_DPM_GFXCLK_BIT),
|
||||
@@ -1053,8 +1057,35 @@ static bool smu_v13_0_7_is_od_feature_supported(struct smu_context *smu,
|
||||
PPTable_t *pptable = smu->smu_table.driver_pptable;
|
||||
const OverDriveLimits_t * const overdrive_upperlimits =
|
||||
&pptable->SkuTable.OverDriveLimitsBasicMax;
|
||||
int32_t min_value, max_value;
|
||||
bool feature_enabled;
|
||||
|
||||
return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit);
|
||||
switch (od_feature_bit) {
|
||||
case PP_OD_FEATURE_FAN_CURVE_BIT:
|
||||
feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
|
||||
if (feature_enabled) {
|
||||
smu_v13_0_7_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_TEMP,
|
||||
&min_value, &max_value);
|
||||
if (!min_value && !max_value) {
|
||||
feature_enabled = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
smu_v13_0_7_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_PWM,
|
||||
&min_value, &max_value);
|
||||
if (!min_value && !max_value) {
|
||||
feature_enabled = false;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
return feature_enabled;
|
||||
}
|
||||
|
||||
static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
|
||||
|
||||
@@ -56,6 +56,10 @@
|
||||
|
||||
#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
|
||||
|
||||
static void smu_v14_0_2_get_od_setting_limits(struct smu_context *smu,
|
||||
int od_feature_bit,
|
||||
int32_t *min, int32_t *max);
|
||||
|
||||
static const struct smu_feature_bits smu_v14_0_2_dpm_features = {
|
||||
.bits = { SMU_FEATURE_BIT_INIT(FEATURE_DPM_GFXCLK_BIT),
|
||||
SMU_FEATURE_BIT_INIT(FEATURE_DPM_UCLK_BIT),
|
||||
@@ -922,8 +926,35 @@ static bool smu_v14_0_2_is_od_feature_supported(struct smu_context *smu,
|
||||
PPTable_t *pptable = smu->smu_table.driver_pptable;
|
||||
const OverDriveLimits_t * const overdrive_upperlimits =
|
||||
&pptable->SkuTable.OverDriveLimitsBasicMax;
|
||||
int32_t min_value, max_value;
|
||||
bool feature_enabled;
|
||||
|
||||
return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit);
|
||||
switch (od_feature_bit) {
|
||||
case PP_OD_FEATURE_FAN_CURVE_BIT:
|
||||
feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
|
||||
if (feature_enabled) {
|
||||
smu_v14_0_2_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_TEMP,
|
||||
&min_value, &max_value);
|
||||
if (!min_value && !max_value) {
|
||||
feature_enabled = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
smu_v14_0_2_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_PWM,
|
||||
&min_value, &max_value);
|
||||
if (!min_value && !max_value) {
|
||||
feature_enabled = false;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
return feature_enabled;
|
||||
}
|
||||
|
||||
static void smu_v14_0_2_get_od_setting_limits(struct smu_context *smu,
|
||||
|
||||
Reference in New Issue
Block a user