Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+192 -60
+2 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
··· 692 692 goto err_ib_sched; 693 693 } 694 694 695 - /* Drop the initial kref_init count (see drm_sched_main as example) */ 696 - dma_fence_put(f); 697 695 ret = dma_fence_wait(f, false); 696 + /* Drop the returned fence reference after the wait completes */ 697 + dma_fence_put(f); 698 698 699 699 err_ib_sched: 700 700 amdgpu_job_free(job);
+11 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
··· 4207 4207 4208 4208 static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev) 4209 4209 { 4210 - char *input = amdgpu_lockup_timeout; 4210 + char buf[AMDGPU_MAX_TIMEOUT_PARAM_LENGTH]; 4211 + char *input = buf; 4211 4212 char *timeout_setting = NULL; 4212 4213 int index = 0; 4213 4214 long timeout; ··· 4218 4217 adev->gfx_timeout = adev->compute_timeout = adev->sdma_timeout = 4219 4218 adev->video_timeout = msecs_to_jiffies(2000); 4220 4219 4221 - if (!strnlen(input, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH)) 4220 + if (!strnlen(amdgpu_lockup_timeout, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH)) 4222 4221 return 0; 4222 + 4223 + /* 4224 + * strsep() destructively modifies its input by replacing delimiters 4225 + * with '\0'. Use a stack copy so the global module parameter buffer 4226 + * remains intact for multi-GPU systems where this function is called 4227 + * once per device. 4228 + */ 4229 + strscpy(buf, amdgpu_lockup_timeout, sizeof(buf)); 4223 4230 4224 4231 while ((timeout_setting = strsep(&input, ",")) && 4225 4232 strnlen(timeout_setting, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH)) {
+32 -13
drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
··· 35 35 * PASIDs are global address space identifiers that can be shared 36 36 * between the GPU, an IOMMU and the driver. VMs on different devices 37 37 * may use the same PASID if they share the same address 38 - * space. Therefore PASIDs are allocated using a global IDA. VMs are 39 - * looked up from the PASID per amdgpu_device. 38 + * space. Therefore PASIDs are allocated using IDR cyclic allocator 39 + * (similar to kernel PID allocation) which naturally delays reuse. 40 + * VMs are looked up from the PASID per amdgpu_device. 40 41 */ 41 - static DEFINE_IDA(amdgpu_pasid_ida); 42 + 43 + static DEFINE_IDR(amdgpu_pasid_idr); 44 + static DEFINE_SPINLOCK(amdgpu_pasid_idr_lock); 42 45 43 46 /* Helper to free pasid from a fence callback */ 44 47 struct amdgpu_pasid_cb { ··· 53 50 * amdgpu_pasid_alloc - Allocate a PASID 54 51 * @bits: Maximum width of the PASID in bits, must be at least 1 55 52 * 56 - * Allocates a PASID of the given width while keeping smaller PASIDs 57 - * available if possible. 53 + * Uses kernel's IDR cyclic allocator (same as PID allocation). 54 + * Allocates sequentially with automatic wrap-around. 58 55 * 59 56 * Returns a positive integer on success. Returns %-EINVAL if bits==0. 60 57 * Returns %-ENOSPC if no PASID was available. Returns %-ENOMEM on ··· 62 59 */ 63 60 int amdgpu_pasid_alloc(unsigned int bits) 64 61 { 65 - int pasid = -EINVAL; 62 + int pasid; 66 63 67 - for (bits = min(bits, 31U); bits > 0; bits--) { 68 - pasid = ida_alloc_range(&amdgpu_pasid_ida, 1U << (bits - 1), 69 - (1U << bits) - 1, GFP_KERNEL); 70 - if (pasid != -ENOSPC) 71 - break; 72 - } 64 + if (bits == 0) 65 + return -EINVAL; 66 + 67 + spin_lock(&amdgpu_pasid_idr_lock); 68 + pasid = idr_alloc_cyclic(&amdgpu_pasid_idr, NULL, 1, 69 + 1U << bits, GFP_KERNEL); 70 + spin_unlock(&amdgpu_pasid_idr_lock); 73 71 74 72 if (pasid >= 0) 75 73 trace_amdgpu_pasid_allocated(pasid); ··· 85 81 void amdgpu_pasid_free(u32 pasid) 86 82 { 87 83 trace_amdgpu_pasid_freed(pasid); 88 - ida_free(&amdgpu_pasid_ida, pasid); 84 + 85 + spin_lock(&amdgpu_pasid_idr_lock); 86 + idr_remove(&amdgpu_pasid_idr, pasid); 87 + spin_unlock(&amdgpu_pasid_idr_lock); 89 88 } 90 89 91 90 static void amdgpu_pasid_free_cb(struct dma_fence *fence, ··· 622 615 dma_fence_put(id->pasid_mapping); 623 616 } 624 617 } 618 + } 619 + 620 + /** 621 + * amdgpu_pasid_mgr_cleanup - cleanup PASID manager 622 + * 623 + * Cleanup the IDR allocator. 624 + */ 625 + void amdgpu_pasid_mgr_cleanup(void) 626 + { 627 + spin_lock(&amdgpu_pasid_idr_lock); 628 + idr_destroy(&amdgpu_pasid_idr); 629 + spin_unlock(&amdgpu_pasid_idr_lock); 625 630 }
+1
drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
··· 74 74 void amdgpu_pasid_free(u32 pasid); 75 75 void amdgpu_pasid_free_delayed(struct dma_resv *resv, 76 76 u32 pasid); 77 + void amdgpu_pasid_mgr_cleanup(void); 77 78 78 79 bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev, 79 80 struct amdgpu_vmid *id);
+4 -3
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
··· 2898 2898 xa_destroy(&adev->vm_manager.pasids); 2899 2899 2900 2900 amdgpu_vmid_mgr_fini(adev); 2901 + amdgpu_pasid_mgr_cleanup(); 2901 2902 } 2902 2903 2903 2904 /** ··· 2974 2973 if (!root) 2975 2974 return false; 2976 2975 2977 - addr /= AMDGPU_GPU_PAGE_SIZE; 2978 - 2979 2976 if (is_compute_context && !svm_range_restore_pages(adev, pasid, vmid, 2980 - node_id, addr, ts, write_fault)) { 2977 + node_id, addr >> PAGE_SHIFT, ts, write_fault)) { 2981 2978 amdgpu_bo_unref(&root); 2982 2979 return true; 2983 2980 } 2981 + 2982 + addr /= AMDGPU_GPU_PAGE_SIZE; 2984 2983 2985 2984 r = amdgpu_bo_reserve(root, true); 2986 2985 if (r)
+3 -3
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
··· 3170 3170 struct kfd_process *process; 3171 3171 int ret; 3172 3172 3173 - /* Each FD owns only one kfd_process */ 3174 - if (p->context_id != KFD_CONTEXT_ID_PRIMARY) 3173 + if (!filep->private_data || !p) 3175 3174 return -EINVAL; 3176 3175 3177 - if (!filep->private_data || !p) 3176 + /* Each FD owns only one kfd_process */ 3177 + if (p->context_id != KFD_CONTEXT_ID_PRIMARY) 3178 3178 return -EINVAL; 3179 3179 3180 3180 mutex_lock(&kfd_processes_mutex);
+8 -2
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 3909 3909 3910 3910 aconnector->dc_sink = sink; 3911 3911 dc_sink_retain(aconnector->dc_sink); 3912 + drm_edid_free(aconnector->drm_edid); 3913 + aconnector->drm_edid = NULL; 3912 3914 if (sink->dc_edid.length == 0) { 3913 - aconnector->drm_edid = NULL; 3914 3915 hdmi_cec_unset_edid(aconnector); 3915 3916 if (aconnector->dc_link->aux_mode) { 3916 3917 drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux); ··· 5423 5422 caps = &dm->backlight_caps[aconnector->bl_idx]; 5424 5423 5425 5424 /* Only offer ABM property when non-OLED and user didn't turn off by module parameter */ 5426 - if (!caps->ext_caps->bits.oled && amdgpu_dm_abm_level < 0) 5425 + if (caps->ext_caps && !caps->ext_caps->bits.oled && amdgpu_dm_abm_level < 0) 5427 5426 drm_object_attach_property(&aconnector->base.base, 5428 5427 dm->adev->mode_info.abm_level_property, 5429 5428 ABM_SYSFS_CONTROL); ··· 12524 12523 } 12525 12524 12526 12525 if (dc_resource_is_dsc_encoding_supported(dc)) { 12526 + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { 12527 + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); 12528 + dm_new_crtc_state->mode_changed_independent_from_dsc = new_crtc_state->mode_changed; 12529 + } 12530 + 12527 12531 for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { 12528 12532 if (drm_atomic_crtc_needs_modeset(new_crtc_state)) { 12529 12533 ret = add_affected_mst_dsc_crtcs(state, crtc);
+1
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
··· 984 984 985 985 bool freesync_vrr_info_changed; 986 986 987 + bool mode_changed_independent_from_dsc; 987 988 bool dsc_force_changed; 988 989 bool vrr_supported; 989 990 struct mod_freesync_config freesync_config;
+3 -1
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
··· 1744 1744 int ind = find_crtc_index_in_state_by_stream(state, stream); 1745 1745 1746 1746 if (ind >= 0) { 1747 + struct dm_crtc_state *dm_new_crtc_state = to_dm_crtc_state(state->crtcs[ind].new_state); 1748 + 1747 1749 DRM_INFO_ONCE("%s:%d MST_DSC no mode changed for stream 0x%p\n", 1748 1750 __func__, __LINE__, stream); 1749 - state->crtcs[ind].new_state->mode_changed = 0; 1751 + dm_new_crtc_state->base.mode_changed = dm_new_crtc_state->mode_changed_independent_from_dsc; 1750 1752 } 1751 1753 } 1752 1754 }
+2 -4
drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c
··· 650 650 return &enc110->base; 651 651 } 652 652 653 - if (enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) 654 - return NULL; 655 - 656 653 link_regs_id = 657 654 map_transmitter_id_to_phy_instance(enc_init_data->transmitter); 658 655 ··· 658 661 &link_enc_feature, 659 662 &link_enc_regs[link_regs_id], 660 663 &link_enc_aux_regs[enc_init_data->channel - 1], 661 - &link_enc_hpd_regs[enc_init_data->hpd_source]); 664 + enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ? 665 + NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]); 662 666 return &enc110->base; 663 667 } 664 668
+3 -2
drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c
··· 671 671 kzalloc_obj(struct dce110_link_encoder); 672 672 int link_regs_id; 673 673 674 - if (!enc110 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) 674 + if (!enc110) 675 675 return NULL; 676 676 677 677 link_regs_id = ··· 682 682 &link_enc_feature, 683 683 &link_enc_regs[link_regs_id], 684 684 &link_enc_aux_regs[enc_init_data->channel - 1], 685 - &link_enc_hpd_regs[enc_init_data->hpd_source]); 685 + enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ? 686 + NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]); 686 687 return &enc110->base; 687 688 } 688 689
+3 -2
drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c
··· 632 632 kzalloc_obj(struct dce110_link_encoder); 633 633 int link_regs_id; 634 634 635 - if (!enc110 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) 635 + if (!enc110) 636 636 return NULL; 637 637 638 638 link_regs_id = ··· 643 643 &link_enc_feature, 644 644 &link_enc_regs[link_regs_id], 645 645 &link_enc_aux_regs[enc_init_data->channel - 1], 646 - &link_enc_hpd_regs[enc_init_data->hpd_source]); 646 + enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ? 647 + NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]); 647 648 return &enc110->base; 648 649 } 649 650
+3 -2
drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c
··· 716 716 kzalloc_obj(struct dce110_link_encoder); 717 717 int link_regs_id; 718 718 719 - if (!enc110 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) 719 + if (!enc110) 720 720 return NULL; 721 721 722 722 link_regs_id = ··· 727 727 &link_enc_feature, 728 728 &link_enc_regs[link_regs_id], 729 729 &link_enc_aux_regs[enc_init_data->channel - 1], 730 - &link_enc_hpd_regs[enc_init_data->hpd_source]); 730 + enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ? 731 + NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]); 731 732 732 733 return &enc110->base; 733 734 }
+6 -8
drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c
··· 746 746 return &enc110->base; 747 747 } 748 748 749 - if (enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) 750 - return NULL; 751 - 752 749 link_regs_id = 753 750 map_transmitter_id_to_phy_instance(enc_init_data->transmitter); 754 751 755 752 dce60_link_encoder_construct(enc110, 756 - enc_init_data, 757 - &link_enc_feature, 758 - &link_enc_regs[link_regs_id], 759 - &link_enc_aux_regs[enc_init_data->channel - 1], 760 - &link_enc_hpd_regs[enc_init_data->hpd_source]); 753 + enc_init_data, 754 + &link_enc_feature, 755 + &link_enc_regs[link_regs_id], 756 + &link_enc_aux_regs[enc_init_data->channel - 1], 757 + enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ? 758 + NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]); 761 759 return &enc110->base; 762 760 } 763 761
+2 -4
drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c
··· 752 752 return &enc110->base; 753 753 } 754 754 755 - if (enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) 756 - return NULL; 757 - 758 755 link_regs_id = 759 756 map_transmitter_id_to_phy_instance(enc_init_data->transmitter); 760 757 ··· 760 763 &link_enc_feature, 761 764 &link_enc_regs[link_regs_id], 762 765 &link_enc_aux_regs[enc_init_data->channel - 1], 763 - &link_enc_hpd_regs[enc_init_data->hpd_source]); 766 + enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ? 767 + NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]); 764 768 return &enc110->base; 765 769 } 766 770
+32 -1
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
··· 59 59 60 60 #define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) 61 61 62 + static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu, 63 + int od_feature_bit, 64 + int32_t *min, int32_t *max); 65 + 62 66 static const struct smu_feature_bits smu_v13_0_0_dpm_features = { 63 67 .bits = { 64 68 SMU_FEATURE_BIT_INIT(FEATURE_DPM_GFXCLK_BIT), ··· 1047 1043 PPTable_t *pptable = smu->smu_table.driver_pptable; 1048 1044 const OverDriveLimits_t * const overdrive_upperlimits = 1049 1045 &pptable->SkuTable.OverDriveLimitsBasicMax; 1046 + int32_t min_value, max_value; 1047 + bool feature_enabled; 1050 1048 1051 - return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit); 1049 + switch (od_feature_bit) { 1050 + case PP_OD_FEATURE_FAN_CURVE_BIT: 1051 + feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit)); 1052 + if (feature_enabled) { 1053 + smu_v13_0_0_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_TEMP, 1054 + &min_value, &max_value); 1055 + if (!min_value && !max_value) { 1056 + feature_enabled = false; 1057 + goto out; 1058 + } 1059 + 1060 + smu_v13_0_0_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_PWM, 1061 + &min_value, &max_value); 1062 + if (!min_value && !max_value) { 1063 + feature_enabled = false; 1064 + goto out; 1065 + } 1066 + } 1067 + break; 1068 + default: 1069 + feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit)); 1070 + break; 1071 + } 1072 + 1073 + out: 1074 + return feature_enabled; 1052 1075 } 1053 1076 1054 1077 static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu,
+12 -9
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
··· 1391 1391 break; 1392 1392 case SMU_OD_MCLK: 1393 1393 if (!smu_v13_0_6_cap_supported(smu, SMU_CAP(SET_UCLK_MAX))) 1394 - return 0; 1394 + return -EOPNOTSUPP; 1395 1395 1396 1396 size += sysfs_emit_at(buf, size, "%s:\n", "OD_MCLK"); 1397 1397 size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n", ··· 2122 2122 { 2123 2123 struct smu_dpm_context *smu_dpm = &(smu->smu_dpm); 2124 2124 struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context; 2125 + struct smu_dpm_table *uclk_table = &dpm_context->dpm_tables.uclk_table; 2125 2126 struct smu_umd_pstate_table *pstate_table = &smu->pstate_table; 2126 2127 uint32_t min_clk; 2127 2128 uint32_t max_clk; ··· 2222 2221 if (ret) 2223 2222 return ret; 2224 2223 2225 - min_clk = SMU_DPM_TABLE_MIN( 2226 - &dpm_context->dpm_tables.uclk_table); 2227 - max_clk = SMU_DPM_TABLE_MAX( 2228 - &dpm_context->dpm_tables.uclk_table); 2229 - ret = smu_v13_0_6_set_soft_freq_limited_range( 2230 - smu, SMU_UCLK, min_clk, max_clk, false); 2231 - if (ret) 2232 - return ret; 2224 + if (SMU_DPM_TABLE_MAX(uclk_table) != 2225 + pstate_table->uclk_pstate.curr.max) { 2226 + min_clk = SMU_DPM_TABLE_MIN(&dpm_context->dpm_tables.uclk_table); 2227 + max_clk = SMU_DPM_TABLE_MAX(&dpm_context->dpm_tables.uclk_table); 2228 + ret = smu_v13_0_6_set_soft_freq_limited_range(smu, 2229 + SMU_UCLK, min_clk, 2230 + max_clk, false); 2231 + if (ret) 2232 + return ret; 2233 + } 2233 2234 smu_v13_0_reset_custom_level(smu); 2234 2235 } 2235 2236 break;
+32 -1
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
··· 59 59 60 60 #define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) 61 61 62 + static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu, 63 + int od_feature_bit, 64 + int32_t *min, int32_t *max); 65 + 62 66 static const struct smu_feature_bits smu_v13_0_7_dpm_features = { 63 67 .bits = { 64 68 SMU_FEATURE_BIT_INIT(FEATURE_DPM_GFXCLK_BIT), ··· 1057 1053 PPTable_t *pptable = smu->smu_table.driver_pptable; 1058 1054 const OverDriveLimits_t * const overdrive_upperlimits = 1059 1055 &pptable->SkuTable.OverDriveLimitsBasicMax; 1056 + int32_t min_value, max_value; 1057 + bool feature_enabled; 1060 1058 1061 - return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit); 1059 + switch (od_feature_bit) { 1060 + case PP_OD_FEATURE_FAN_CURVE_BIT: 1061 + feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit)); 1062 + if (feature_enabled) { 1063 + smu_v13_0_7_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_TEMP, 1064 + &min_value, &max_value); 1065 + if (!min_value && !max_value) { 1066 + feature_enabled = false; 1067 + goto out; 1068 + } 1069 + 1070 + smu_v13_0_7_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_PWM, 1071 + &min_value, &max_value); 1072 + if (!min_value && !max_value) { 1073 + feature_enabled = false; 1074 + goto out; 1075 + } 1076 + } 1077 + break; 1078 + default: 1079 + feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit)); 1080 + break; 1081 + } 1082 + 1083 + out: 1084 + return feature_enabled; 1062 1085 } 1063 1086 1064 1087 static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
+32 -1
drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
··· 56 56 57 57 #define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) 58 58 59 + static void smu_v14_0_2_get_od_setting_limits(struct smu_context *smu, 60 + int od_feature_bit, 61 + int32_t *min, int32_t *max); 62 + 59 63 static const struct smu_feature_bits smu_v14_0_2_dpm_features = { 60 64 .bits = { SMU_FEATURE_BIT_INIT(FEATURE_DPM_GFXCLK_BIT), 61 65 SMU_FEATURE_BIT_INIT(FEATURE_DPM_UCLK_BIT), ··· 926 922 PPTable_t *pptable = smu->smu_table.driver_pptable; 927 923 const OverDriveLimits_t * const overdrive_upperlimits = 928 924 &pptable->SkuTable.OverDriveLimitsBasicMax; 925 + int32_t min_value, max_value; 926 + bool feature_enabled; 929 927 930 - return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit); 928 + switch (od_feature_bit) { 929 + case PP_OD_FEATURE_FAN_CURVE_BIT: 930 + feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit)); 931 + if (feature_enabled) { 932 + smu_v14_0_2_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_TEMP, 933 + &min_value, &max_value); 934 + if (!min_value && !max_value) { 935 + feature_enabled = false; 936 + goto out; 937 + } 938 + 939 + smu_v14_0_2_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_PWM, 940 + &min_value, &max_value); 941 + if (!min_value && !max_value) { 942 + feature_enabled = false; 943 + goto out; 944 + } 945 + } 946 + break; 947 + default: 948 + feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit)); 949 + break; 950 + } 951 + 952 + out: 953 + return feature_enabled; 931 954 } 932 955 933 956 static void smu_v14_0_2_get_od_setting_limits(struct smu_context *smu,