Commit c31a72db authored by Dave Airlie's avatar Dave Airlie

Merge tag 'amd-drm-fixes-6.3-2023-03-15' of...

Merge tag 'amd-drm-fixes-6.3-2023-03-15' of https://gitlab.freedesktop.org/agd5f/linux into drm-fixes

amd-drm-fixes-6.3-2023-03-15:

amdgpu:
- SMU 13 update
- RDNA2 suspend/resume fix when overclocking is enabled
- SRIOV VCN fixes
- HDCP suspend/resume fix
- Fix drm polling splat regression
- Fix dirty rectangle tracking for PSR
- Fix vangogh regression on certain BIOSes
- Misc display fixes
- Suspend/resume IOMMU regression fix

amdkfd:
- Fix BO offset for multi-VMA page migration
- Fix a possible double free
- Fix potential use after free
- Fix process cleanup on module exit
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230315224400.7558-1-alexander.deucher@amd.com
parents 2a210e6a f3921a9a
...@@ -4145,8 +4145,6 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon) ...@@ -4145,8 +4145,6 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D3)) if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D3))
DRM_WARN("smart shift update failed\n"); DRM_WARN("smart shift update failed\n");
drm_kms_helper_poll_disable(dev);
if (fbcon) if (fbcon)
drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, true); drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, true);
...@@ -4243,8 +4241,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) ...@@ -4243,8 +4241,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
if (fbcon) if (fbcon)
drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, false); drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, false);
drm_kms_helper_poll_enable(dev);
amdgpu_ras_resume(adev); amdgpu_ras_resume(adev);
if (adev->mode_info.num_crtc) { if (adev->mode_info.num_crtc) {
......
...@@ -1618,6 +1618,8 @@ int amdgpu_display_suspend_helper(struct amdgpu_device *adev) ...@@ -1618,6 +1618,8 @@ int amdgpu_display_suspend_helper(struct amdgpu_device *adev)
struct drm_connector_list_iter iter; struct drm_connector_list_iter iter;
int r; int r;
drm_kms_helper_poll_disable(dev);
/* turn off display hw */ /* turn off display hw */
drm_modeset_lock_all(dev); drm_modeset_lock_all(dev);
drm_connector_list_iter_begin(dev, &iter); drm_connector_list_iter_begin(dev, &iter);
...@@ -1694,6 +1696,8 @@ int amdgpu_display_resume_helper(struct amdgpu_device *adev) ...@@ -1694,6 +1696,8 @@ int amdgpu_display_resume_helper(struct amdgpu_device *adev)
drm_modeset_unlock_all(dev); drm_modeset_unlock_all(dev);
drm_kms_helper_poll_enable(dev);
return 0; return 0;
} }
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/dmi.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <drm/drm_drv.h> #include <drm/drm_drv.h>
...@@ -114,6 +115,24 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev) ...@@ -114,6 +115,24 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)) (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true; adev->vcn.indirect_sram = true;
/*
* Some Steam Deck's BIOS versions are incompatible with the
* indirect SRAM mode, leading to amdgpu being unable to get
* properly probed (and even potentially crashing the kernel).
* Hence, check for these versions here - notice this is
* restricted to Vangogh (Deck's APU).
*/
if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(3, 0, 2)) {
const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
!strncmp("F7A0114", bios_ver, 7))) {
adev->vcn.indirect_sram = false;
dev_info(adev->dev,
"Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
}
}
hdr = (const struct common_firmware_header *)adev->vcn.fw->data; hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version); adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
......
...@@ -124,6 +124,8 @@ enum AMDGIM_FEATURE_FLAG { ...@@ -124,6 +124,8 @@ enum AMDGIM_FEATURE_FLAG {
AMDGIM_FEATURE_PP_ONE_VF = (1 << 4), AMDGIM_FEATURE_PP_ONE_VF = (1 << 4),
/* Indirect Reg Access enabled */ /* Indirect Reg Access enabled */
AMDGIM_FEATURE_INDIRECT_REG_ACCESS = (1 << 5), AMDGIM_FEATURE_INDIRECT_REG_ACCESS = (1 << 5),
/* AV1 Support MODE*/
AMDGIM_FEATURE_AV1_SUPPORT = (1 << 6),
}; };
enum AMDGIM_REG_ACCESS_FLAG { enum AMDGIM_REG_ACCESS_FLAG {
...@@ -322,6 +324,8 @@ static inline bool is_virtual_machine(void) ...@@ -322,6 +324,8 @@ static inline bool is_virtual_machine(void)
((!amdgpu_in_reset(adev)) && adev->virt.tdr_debug) ((!amdgpu_in_reset(adev)) && adev->virt.tdr_debug)
#define amdgpu_sriov_is_normal(adev) \ #define amdgpu_sriov_is_normal(adev) \
((!amdgpu_in_reset(adev)) && (!adev->virt.tdr_debug)) ((!amdgpu_in_reset(adev)) && (!adev->virt.tdr_debug))
#define amdgpu_sriov_is_av1_support(adev) \
((adev)->virt.gim_feature & AMDGIM_FEATURE_AV1_SUPPORT)
bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev); bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev);
void amdgpu_virt_init_setting(struct amdgpu_device *adev); void amdgpu_virt_init_setting(struct amdgpu_device *adev);
void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev, void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev,
......
...@@ -93,7 +93,8 @@ union amd_sriov_msg_feature_flags { ...@@ -93,7 +93,8 @@ union amd_sriov_msg_feature_flags {
uint32_t mm_bw_management : 1; uint32_t mm_bw_management : 1;
uint32_t pp_one_vf_mode : 1; uint32_t pp_one_vf_mode : 1;
uint32_t reg_indirect_acc : 1; uint32_t reg_indirect_acc : 1;
uint32_t reserved : 26; uint32_t av1_support : 1;
uint32_t reserved : 25;
} flags; } flags;
uint32_t all; uint32_t all;
}; };
......
...@@ -1055,8 +1055,8 @@ static int nv_common_late_init(void *handle) ...@@ -1055,8 +1055,8 @@ static int nv_common_late_init(void *handle)
amdgpu_virt_update_sriov_video_codec(adev, amdgpu_virt_update_sriov_video_codec(adev,
sriov_sc_video_codecs_encode_array, sriov_sc_video_codecs_encode_array,
ARRAY_SIZE(sriov_sc_video_codecs_encode_array), ARRAY_SIZE(sriov_sc_video_codecs_encode_array),
sriov_sc_video_codecs_decode_array_vcn1, sriov_sc_video_codecs_decode_array_vcn0,
ARRAY_SIZE(sriov_sc_video_codecs_decode_array_vcn1)); ARRAY_SIZE(sriov_sc_video_codecs_decode_array_vcn0));
} }
} }
......
...@@ -102,6 +102,59 @@ static const struct amdgpu_video_codecs vcn_4_0_0_video_codecs_decode_vcn1 = ...@@ -102,6 +102,59 @@ static const struct amdgpu_video_codecs vcn_4_0_0_video_codecs_decode_vcn1 =
.codec_array = vcn_4_0_0_video_codecs_decode_array_vcn1, .codec_array = vcn_4_0_0_video_codecs_decode_array_vcn1,
}; };
/* SRIOV SOC21, not const since data is controlled by host */
static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_encode_array_vcn0[] = {
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)},
};
static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_encode_array_vcn1[] = {
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)},
};
static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_encode_vcn0 = {
.codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn0),
.codec_array = sriov_vcn_4_0_0_video_codecs_encode_array_vcn0,
};
static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_encode_vcn1 = {
.codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn1),
.codec_array = sriov_vcn_4_0_0_video_codecs_encode_array_vcn1,
};
static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_decode_array_vcn0[] = {
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)},
};
static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_decode_array_vcn1[] = {
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)},
};
static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_decode_vcn0 = {
.codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn0),
.codec_array = sriov_vcn_4_0_0_video_codecs_decode_array_vcn0,
};
static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_decode_vcn1 = {
.codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn1),
.codec_array = sriov_vcn_4_0_0_video_codecs_decode_array_vcn1,
};
static int soc21_query_video_codecs(struct amdgpu_device *adev, bool encode, static int soc21_query_video_codecs(struct amdgpu_device *adev, bool encode,
const struct amdgpu_video_codecs **codecs) const struct amdgpu_video_codecs **codecs)
{ {
...@@ -112,16 +165,31 @@ static int soc21_query_video_codecs(struct amdgpu_device *adev, bool encode, ...@@ -112,16 +165,31 @@ static int soc21_query_video_codecs(struct amdgpu_device *adev, bool encode,
case IP_VERSION(4, 0, 0): case IP_VERSION(4, 0, 0):
case IP_VERSION(4, 0, 2): case IP_VERSION(4, 0, 2):
case IP_VERSION(4, 0, 4): case IP_VERSION(4, 0, 4):
if (adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) { if (amdgpu_sriov_vf(adev)) {
if (encode) if ((adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) ||
*codecs = &vcn_4_0_0_video_codecs_encode_vcn1; !amdgpu_sriov_is_av1_support(adev)) {
else if (encode)
*codecs = &vcn_4_0_0_video_codecs_decode_vcn1; *codecs = &sriov_vcn_4_0_0_video_codecs_encode_vcn1;
else
*codecs = &sriov_vcn_4_0_0_video_codecs_decode_vcn1;
} else {
if (encode)
*codecs = &sriov_vcn_4_0_0_video_codecs_encode_vcn0;
else
*codecs = &sriov_vcn_4_0_0_video_codecs_decode_vcn0;
}
} else { } else {
if (encode) if ((adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0)) {
*codecs = &vcn_4_0_0_video_codecs_encode_vcn0; if (encode)
else *codecs = &vcn_4_0_0_video_codecs_encode_vcn1;
*codecs = &vcn_4_0_0_video_codecs_decode_vcn0; else
*codecs = &vcn_4_0_0_video_codecs_decode_vcn1;
} else {
if (encode)
*codecs = &vcn_4_0_0_video_codecs_encode_vcn0;
else
*codecs = &vcn_4_0_0_video_codecs_decode_vcn0;
}
} }
return 0; return 0;
default: default:
...@@ -730,8 +798,23 @@ static int soc21_common_late_init(void *handle) ...@@ -730,8 +798,23 @@ static int soc21_common_late_init(void *handle)
{ {
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (amdgpu_sriov_vf(adev)) if (amdgpu_sriov_vf(adev)) {
xgpu_nv_mailbox_get_irq(adev); xgpu_nv_mailbox_get_irq(adev);
if ((adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) ||
!amdgpu_sriov_is_av1_support(adev)) {
amdgpu_virt_update_sriov_video_codec(adev,
sriov_vcn_4_0_0_video_codecs_encode_array_vcn1,
ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn1),
sriov_vcn_4_0_0_video_codecs_decode_array_vcn1,
ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn1));
} else {
amdgpu_virt_update_sriov_video_codec(adev,
sriov_vcn_4_0_0_video_codecs_encode_array_vcn0,
ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn0),
sriov_vcn_4_0_0_video_codecs_decode_array_vcn0,
ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn0));
}
}
return 0; return 0;
} }
......
...@@ -1312,14 +1312,14 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, ...@@ -1312,14 +1312,14 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
args->n_success = i+1; args->n_success = i+1;
} }
mutex_unlock(&p->mutex);
err = amdgpu_amdkfd_gpuvm_sync_memory(dev->adev, (struct kgd_mem *) mem, true); err = amdgpu_amdkfd_gpuvm_sync_memory(dev->adev, (struct kgd_mem *) mem, true);
if (err) { if (err) {
pr_debug("Sync memory failed, wait interrupted by user signal\n"); pr_debug("Sync memory failed, wait interrupted by user signal\n");
goto sync_memory_failed; goto sync_memory_failed;
} }
mutex_unlock(&p->mutex);
/* Flush TLBs after waiting for the page table updates to complete */ /* Flush TLBs after waiting for the page table updates to complete */
for (i = 0; i < args->n_devices; i++) { for (i = 0; i < args->n_devices; i++) {
peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]);
...@@ -1335,9 +1335,9 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, ...@@ -1335,9 +1335,9 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
bind_process_to_device_failed: bind_process_to_device_failed:
get_mem_obj_from_handle_failed: get_mem_obj_from_handle_failed:
map_memory_to_gpu_failed: map_memory_to_gpu_failed:
sync_memory_failed:
mutex_unlock(&p->mutex); mutex_unlock(&p->mutex);
copy_from_user_failed: copy_from_user_failed:
sync_memory_failed:
kfree(devices_arr); kfree(devices_arr);
return err; return err;
...@@ -1351,6 +1351,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, ...@@ -1351,6 +1351,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
void *mem; void *mem;
long err = 0; long err = 0;
uint32_t *devices_arr = NULL, i; uint32_t *devices_arr = NULL, i;
bool flush_tlb;
if (!args->n_devices) { if (!args->n_devices) {
pr_debug("Device IDs array empty\n"); pr_debug("Device IDs array empty\n");
...@@ -1403,16 +1404,19 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, ...@@ -1403,16 +1404,19 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
} }
args->n_success = i+1; args->n_success = i+1;
} }
mutex_unlock(&p->mutex);
if (kfd_flush_tlb_after_unmap(pdd->dev)) { flush_tlb = kfd_flush_tlb_after_unmap(pdd->dev);
if (flush_tlb) {
err = amdgpu_amdkfd_gpuvm_sync_memory(pdd->dev->adev, err = amdgpu_amdkfd_gpuvm_sync_memory(pdd->dev->adev,
(struct kgd_mem *) mem, true); (struct kgd_mem *) mem, true);
if (err) { if (err) {
pr_debug("Sync memory failed, wait interrupted by user signal\n"); pr_debug("Sync memory failed, wait interrupted by user signal\n");
goto sync_memory_failed; goto sync_memory_failed;
} }
}
mutex_unlock(&p->mutex);
if (flush_tlb) {
/* Flush TLBs after waiting for the page table updates to complete */ /* Flush TLBs after waiting for the page table updates to complete */
for (i = 0; i < args->n_devices; i++) { for (i = 0; i < args->n_devices; i++) {
peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]);
...@@ -1428,9 +1432,9 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, ...@@ -1428,9 +1432,9 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
bind_process_to_device_failed: bind_process_to_device_failed:
get_mem_obj_from_handle_failed: get_mem_obj_from_handle_failed:
unmap_memory_from_gpu_failed: unmap_memory_from_gpu_failed:
sync_memory_failed:
mutex_unlock(&p->mutex); mutex_unlock(&p->mutex);
copy_from_user_failed: copy_from_user_failed:
sync_memory_failed:
kfree(devices_arr); kfree(devices_arr);
return err; return err;
} }
......
...@@ -59,6 +59,7 @@ static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size, ...@@ -59,6 +59,7 @@ static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size,
unsigned int chunk_size); unsigned int chunk_size);
static void kfd_gtt_sa_fini(struct kfd_dev *kfd); static void kfd_gtt_sa_fini(struct kfd_dev *kfd);
static int kfd_resume_iommu(struct kfd_dev *kfd);
static int kfd_resume(struct kfd_dev *kfd); static int kfd_resume(struct kfd_dev *kfd);
static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd) static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd)
...@@ -624,7 +625,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, ...@@ -624,7 +625,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
svm_migrate_init(kfd->adev); svm_migrate_init(kfd->adev);
if (kgd2kfd_resume_iommu(kfd)) if (kfd_resume_iommu(kfd))
goto device_iommu_error; goto device_iommu_error;
if (kfd_resume(kfd)) if (kfd_resume(kfd))
...@@ -772,6 +773,14 @@ int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) ...@@ -772,6 +773,14 @@ int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm)
} }
int kgd2kfd_resume_iommu(struct kfd_dev *kfd) int kgd2kfd_resume_iommu(struct kfd_dev *kfd)
{
if (!kfd->init_complete)
return 0;
return kfd_resume_iommu(kfd);
}
static int kfd_resume_iommu(struct kfd_dev *kfd)
{ {
int err = 0; int err = 0;
......
...@@ -289,7 +289,7 @@ static unsigned long svm_migrate_unsuccessful_pages(struct migrate_vma *migrate) ...@@ -289,7 +289,7 @@ static unsigned long svm_migrate_unsuccessful_pages(struct migrate_vma *migrate)
static int static int
svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange, svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
struct migrate_vma *migrate, struct dma_fence **mfence, struct migrate_vma *migrate, struct dma_fence **mfence,
dma_addr_t *scratch) dma_addr_t *scratch, uint64_t ttm_res_offset)
{ {
uint64_t npages = migrate->npages; uint64_t npages = migrate->npages;
struct device *dev = adev->dev; struct device *dev = adev->dev;
...@@ -299,19 +299,13 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange, ...@@ -299,19 +299,13 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
uint64_t i, j; uint64_t i, j;
int r; int r;
pr_debug("svms 0x%p [0x%lx 0x%lx]\n", prange->svms, prange->start, pr_debug("svms 0x%p [0x%lx 0x%lx 0x%llx]\n", prange->svms, prange->start,
prange->last); prange->last, ttm_res_offset);
src = scratch; src = scratch;
dst = (uint64_t *)(scratch + npages); dst = (uint64_t *)(scratch + npages);
r = svm_range_vram_node_new(adev, prange, true); amdgpu_res_first(prange->ttm_res, ttm_res_offset,
if (r) {
dev_dbg(adev->dev, "fail %d to alloc vram\n", r);
goto out;
}
amdgpu_res_first(prange->ttm_res, prange->offset << PAGE_SHIFT,
npages << PAGE_SHIFT, &cursor); npages << PAGE_SHIFT, &cursor);
for (i = j = 0; i < npages; i++) { for (i = j = 0; i < npages; i++) {
struct page *spage; struct page *spage;
...@@ -391,14 +385,14 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange, ...@@ -391,14 +385,14 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
migrate->dst[i + 3] = 0; migrate->dst[i + 3] = 0;
} }
#endif #endif
out:
return r; return r;
} }
static long static long
svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange, svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
struct vm_area_struct *vma, uint64_t start, struct vm_area_struct *vma, uint64_t start,
uint64_t end, uint32_t trigger) uint64_t end, uint32_t trigger, uint64_t ttm_res_offset)
{ {
struct kfd_process *p = container_of(prange->svms, struct kfd_process, svms); struct kfd_process *p = container_of(prange->svms, struct kfd_process, svms);
uint64_t npages = (end - start) >> PAGE_SHIFT; uint64_t npages = (end - start) >> PAGE_SHIFT;
...@@ -451,7 +445,7 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange, ...@@ -451,7 +445,7 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
else else
pr_debug("0x%lx pages migrated\n", cpages); pr_debug("0x%lx pages migrated\n", cpages);
r = svm_migrate_copy_to_vram(adev, prange, &migrate, &mfence, scratch); r = svm_migrate_copy_to_vram(adev, prange, &migrate, &mfence, scratch, ttm_res_offset);
migrate_vma_pages(&migrate); migrate_vma_pages(&migrate);
pr_debug("successful/cpages/npages 0x%lx/0x%lx/0x%lx\n", pr_debug("successful/cpages/npages 0x%lx/0x%lx/0x%lx\n",
...@@ -499,6 +493,7 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc, ...@@ -499,6 +493,7 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
unsigned long addr, start, end; unsigned long addr, start, end;
struct vm_area_struct *vma; struct vm_area_struct *vma;
struct amdgpu_device *adev; struct amdgpu_device *adev;
uint64_t ttm_res_offset;
unsigned long cpages = 0; unsigned long cpages = 0;
long r = 0; long r = 0;
...@@ -520,6 +515,13 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc, ...@@ -520,6 +515,13 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
start = prange->start << PAGE_SHIFT; start = prange->start << PAGE_SHIFT;
end = (prange->last + 1) << PAGE_SHIFT; end = (prange->last + 1) << PAGE_SHIFT;
r = svm_range_vram_node_new(adev, prange, true);
if (r) {
dev_dbg(adev->dev, "fail %ld to alloc vram\n", r);
return r;
}
ttm_res_offset = prange->offset << PAGE_SHIFT;
for (addr = start; addr < end;) { for (addr = start; addr < end;) {
unsigned long next; unsigned long next;
...@@ -528,18 +530,21 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc, ...@@ -528,18 +530,21 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
break; break;
next = min(vma->vm_end, end); next = min(vma->vm_end, end);
r = svm_migrate_vma_to_vram(adev, prange, vma, addr, next, trigger); r = svm_migrate_vma_to_vram(adev, prange, vma, addr, next, trigger, ttm_res_offset);
if (r < 0) { if (r < 0) {
pr_debug("failed %ld to migrate\n", r); pr_debug("failed %ld to migrate\n", r);
break; break;
} else { } else {
cpages += r; cpages += r;
} }
ttm_res_offset += next - addr;
addr = next; addr = next;
} }
if (cpages) if (cpages)
prange->actual_loc = best_loc; prange->actual_loc = best_loc;
else
svm_range_vram_node_free(prange);
return r < 0 ? r : 0; return r < 0 ? r : 0;
} }
......
...@@ -77,6 +77,7 @@ static int kfd_init(void) ...@@ -77,6 +77,7 @@ static int kfd_init(void)
static void kfd_exit(void) static void kfd_exit(void)
{ {
kfd_cleanup_processes();
kfd_debugfs_fini(); kfd_debugfs_fini();
kfd_process_destroy_wq(); kfd_process_destroy_wq();
kfd_procfs_shutdown(); kfd_procfs_shutdown();
......
...@@ -928,6 +928,7 @@ bool kfd_dev_is_large_bar(struct kfd_dev *dev); ...@@ -928,6 +928,7 @@ bool kfd_dev_is_large_bar(struct kfd_dev *dev);
int kfd_process_create_wq(void); int kfd_process_create_wq(void);
void kfd_process_destroy_wq(void); void kfd_process_destroy_wq(void);
void kfd_cleanup_processes(void);
struct kfd_process *kfd_create_process(struct file *filep); struct kfd_process *kfd_create_process(struct file *filep);
struct kfd_process *kfd_get_process(const struct task_struct *task); struct kfd_process *kfd_get_process(const struct task_struct *task);
struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid); struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid);
......
...@@ -1167,6 +1167,17 @@ static void kfd_process_free_notifier(struct mmu_notifier *mn) ...@@ -1167,6 +1167,17 @@ static void kfd_process_free_notifier(struct mmu_notifier *mn)
kfd_unref_process(container_of(mn, struct kfd_process, mmu_notifier)); kfd_unref_process(container_of(mn, struct kfd_process, mmu_notifier));
} }
static void kfd_process_notifier_release_internal(struct kfd_process *p)
{
cancel_delayed_work_sync(&p->eviction_work);
cancel_delayed_work_sync(&p->restore_work);
/* Indicate to other users that MM is no longer valid */
p->mm = NULL;
mmu_notifier_put(&p->mmu_notifier);
}
static void kfd_process_notifier_release(struct mmu_notifier *mn, static void kfd_process_notifier_release(struct mmu_notifier *mn,
struct mm_struct *mm) struct mm_struct *mm)
{ {
...@@ -1181,17 +1192,22 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn, ...@@ -1181,17 +1192,22 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn,
return; return;
mutex_lock(&kfd_processes_mutex); mutex_lock(&kfd_processes_mutex);
/*
* Do early return if table is empty.
*
* This could potentially happen if this function is called concurrently
* by mmu_notifier and by kfd_cleanup_pocesses.
*
*/
if (hash_empty(kfd_processes_table)) {
mutex_unlock(&kfd_processes_mutex);
return;
}
hash_del_rcu(&p->kfd_processes); hash_del_rcu(&p->kfd_processes);
mutex_unlock(&kfd_processes_mutex); mutex_unlock(&kfd_processes_mutex);
synchronize_srcu(&kfd_processes_srcu); synchronize_srcu(&kfd_processes_srcu);
cancel_delayed_work_sync(&p->eviction_work); kfd_process_notifier_release_internal(p);
cancel_delayed_work_sync(&p->restore_work);
/* Indicate to other users that MM is no longer valid */
p->mm = NULL;
mmu_notifier_put(&p->mmu_notifier);
} }
static const struct mmu_notifier_ops kfd_process_mmu_notifier_ops = { static const struct mmu_notifier_ops kfd_process_mmu_notifier_ops = {
...@@ -1200,6 +1216,43 @@ static const struct mmu_notifier_ops kfd_process_mmu_notifier_ops = { ...@@ -1200,6 +1216,43 @@ static const struct mmu_notifier_ops kfd_process_mmu_notifier_ops = {
.free_notifier = kfd_process_free_notifier, .free_notifier = kfd_process_free_notifier,
}; };
/*
* This code handles the case when driver is being unloaded before all
* mm_struct are released. We need to safely free the kfd_process and
* avoid race conditions with mmu_notifier that might try to free them.
*
*/
void kfd_cleanup_processes(void)
{
struct kfd_process *p;
struct hlist_node *p_temp;
unsigned int temp;
HLIST_HEAD(cleanup_list);
/*
* Move all remaining kfd_process from the process table to a
* temp list for processing. Once done, callback from mmu_notifier
* release will not see the kfd_process in the table and do early return,
* avoiding double free issues.
*/
mutex_lock(&kfd_processes_mutex);
hash_for_each_safe(kfd_processes_table, temp, p_temp, p, kfd_processes) {
hash_del_rcu(&p->kfd_processes);
synchronize_srcu(&kfd_processes_srcu);
hlist_add_head(&p->kfd_processes, &cleanup_list);
}
mutex_unlock(&kfd_processes_mutex);
hlist_for_each_entry_safe(p, p_temp, &cleanup_list, kfd_processes)
kfd_process_notifier_release_internal(p);
/*
* Ensures that all outstanding free_notifier get called, triggering
* the release of the kfd_process struct.
*/
mmu_notifier_synchronize();
}
static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep) static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep)
{ {
unsigned long offset; unsigned long offset;
......
...@@ -218,8 +218,8 @@ static int init_user_queue(struct process_queue_manager *pqm, ...@@ -218,8 +218,8 @@ static int init_user_queue(struct process_queue_manager *pqm,
return 0; return 0;
cleanup: cleanup:
if (dev->shared_resources.enable_mes) uninit_queue(*q);
uninit_queue(*q); *q = NULL;
return retval; return retval;
} }
......
...@@ -5105,9 +5105,9 @@ static void fill_dc_dirty_rects(struct drm_plane *plane, ...@@ -5105,9 +5105,9 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
for (; flip_addrs->dirty_rect_count < num_clips; clips++) for (; flip_addrs->dirty_rect_count < num_clips; clips++)
fill_dc_dirty_rect(new_plane_state->plane, fill_dc_dirty_rect(new_plane_state->plane,
&dirty_rects[i], clips->x1, &dirty_rects[flip_addrs->dirty_rect_count],
clips->y1, clips->x2 - clips->x1, clips->x1, clips->y1,
clips->y2 - clips->y1, clips->x2 - clips->x1, clips->y2 - clips->y1,
&flip_addrs->dirty_rect_count, &flip_addrs->dirty_rect_count,
false); false);
return; return;
......
...@@ -561,7 +561,7 @@ static void update_config(void *handle, struct cp_psp_stream_config *config) ...@@ -561,7 +561,7 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)
link->dp.mst_enabled = config->mst_enabled; link->dp.mst_enabled = config->mst_enabled;
link->dp.usb4_enabled = config->usb4_enabled; link->dp.usb4_enabled = config->usb4_enabled;
display->adjust.disable = MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION; display->adjust.disable = MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION;
link->adjust.auth_delay = 0; link->adjust.auth_delay = 2;
link->adjust.hdcp1.disable = 0; link->adjust.hdcp1.disable = 0;
conn_state = aconnector->base.state; conn_state = aconnector->base.state;
......
...@@ -998,8 +998,5 @@ void dcn30_prepare_bandwidth(struct dc *dc, ...@@ -998,8 +998,5 @@ void dcn30_prepare_bandwidth(struct dc *dc,
dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz); dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz);
dcn20_prepare_bandwidth(dc, context); dcn20_prepare_bandwidth(dc, context);
dc_dmub_srv_p_state_delegate(dc,
context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching, context);
} }
...@@ -1104,7 +1104,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign ...@@ -1104,7 +1104,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign
*k2_div = PIXEL_RATE_DIV_BY_2; *k2_div = PIXEL_RATE_DIV_BY_2;
else else
*k2_div = PIXEL_RATE_DIV_BY_4; *k2_div = PIXEL_RATE_DIV_BY_4;
} else if (dc_is_dp_signal(stream->signal) || dc_is_virtual_signal(stream->signal)) { } else if (dc_is_dp_signal(stream->signal)) {
if (two_pix_per_container) { if (two_pix_per_container) {
*k1_div = PIXEL_RATE_DIV_BY_1; *k1_div = PIXEL_RATE_DIV_BY_1;
*k2_div = PIXEL_RATE_DIV_BY_2; *k2_div = PIXEL_RATE_DIV_BY_2;
......
...@@ -1915,6 +1915,7 @@ int dcn32_populate_dml_pipes_from_context( ...@@ -1915,6 +1915,7 @@ int dcn32_populate_dml_pipes_from_context(
bool subvp_in_use = false; bool subvp_in_use = false;
uint8_t is_pipe_split_expected[MAX_PIPES] = {0}; uint8_t is_pipe_split_expected[MAX_PIPES] = {0};
struct dc_crtc_timing *timing; struct dc_crtc_timing *timing;
bool vsr_odm_support = false;
dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);
...@@ -1932,12 +1933,15 @@ int dcn32_populate_dml_pipes_from_context( ...@@ -1932,12 +1933,15 @@ int dcn32_populate_dml_pipes_from_context(
timing = &pipe->stream->timing; timing = &pipe->stream->timing;
pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal; pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;
vsr_odm_support = (res_ctx->pipe_ctx[i].stream->src.width >= 5120 &&
res_ctx->pipe_ctx[i].stream->src.width > res_ctx->pipe_ctx[i].stream->dst.width);
if (context->stream_count == 1 && if (context->stream_count == 1 &&
context->stream_status[0].plane_count == 1 && context->stream_status[0].plane_count == 1 &&
!dc_is_hdmi_signal(res_ctx->pipe_ctx[i].stream->signal) && !dc_is_hdmi_signal(res_ctx->pipe_ctx[i].stream->signal) &&
is_h_timing_divisible_by_2(res_ctx->pipe_ctx[i].stream) && is_h_timing_divisible_by_2(res_ctx->pipe_ctx[i].stream) &&
pipe->stream->timing.pix_clk_100hz * 100 > DCN3_2_VMIN_DISPCLK_HZ && pipe->stream->timing.pix_clk_100hz * 100 > DCN3_2_VMIN_DISPCLK_HZ &&
dc->debug.enable_single_display_2to1_odm_policy) { dc->debug.enable_single_display_2to1_odm_policy &&
!vsr_odm_support) { //excluding 2to1 ODM combine on >= 5k vsr
pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1; pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1;
} }
pipe_cnt++; pipe_cnt++;
......
...@@ -855,6 +855,7 @@ static bool detect_link_and_local_sink(struct dc_link *link, ...@@ -855,6 +855,7 @@ static bool detect_link_and_local_sink(struct dc_link *link,
struct dc_sink *prev_sink = NULL; struct dc_sink *prev_sink = NULL;
struct dpcd_caps prev_dpcd_caps; struct dpcd_caps prev_dpcd_caps;
enum dc_connection_type new_connection_type = dc_connection_none; enum dc_connection_type new_connection_type = dc_connection_none;
enum dc_connection_type pre_connection_type = link->type;
const uint32_t post_oui_delay = 30; // 30ms const uint32_t post_oui_delay = 30; // 30ms
DC_LOGGER_INIT(link->ctx->logger); DC_LOGGER_INIT(link->ctx->logger);
...@@ -957,6 +958,8 @@ static bool detect_link_and_local_sink(struct dc_link *link, ...@@ -957,6 +958,8 @@ static bool detect_link_and_local_sink(struct dc_link *link,
} }
if (!detect_dp(link, &sink_caps, reason)) { if (!detect_dp(link, &sink_caps, reason)) {
link->type = pre_connection_type;
if (prev_sink) if (prev_sink)
dc_sink_release(prev_sink); dc_sink_release(prev_sink);
return false; return false;
...@@ -1244,11 +1247,16 @@ bool link_detect(struct dc_link *link, enum dc_detect_reason reason) ...@@ -1244,11 +1247,16 @@ bool link_detect(struct dc_link *link, enum dc_detect_reason reason)
bool is_delegated_to_mst_top_mgr = false; bool is_delegated_to_mst_top_mgr = false;
enum dc_connection_type pre_link_type = link->type; enum dc_connection_type pre_link_type = link->type;
DC_LOGGER_INIT(link->ctx->logger);
is_local_sink_detect_success = detect_link_and_local_sink(link, reason); is_local_sink_detect_success = detect_link_and_local_sink(link, reason);
if (is_local_sink_detect_success && link->local_sink) if (is_local_sink_detect_success && link->local_sink)
verify_link_capability(link, link->local_sink, reason); verify_link_capability(link, link->local_sink, reason);
DC_LOG_DC("%s: link_index=%d is_local_sink_detect_success=%d pre_link_type=%d link_type=%d\n", __func__,
link->link_index, is_local_sink_detect_success, pre_link_type, link->type);
if (is_local_sink_detect_success && link->local_sink && if (is_local_sink_detect_success && link->local_sink &&
dc_is_dp_signal(link->local_sink->sink_signal) && dc_is_dp_signal(link->local_sink->sink_signal) &&
link->dpcd_caps.is_mst_capable) link->dpcd_caps.is_mst_capable)
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
// *** IMPORTANT *** // *** IMPORTANT ***
// SMU TEAM: Always increment the interface version if // SMU TEAM: Always increment the interface version if
// any structure is changed in this file // any structure is changed in this file
#define PMFW_DRIVER_IF_VERSION 7 #define PMFW_DRIVER_IF_VERSION 8
typedef struct { typedef struct {
int32_t value; int32_t value;
...@@ -198,7 +198,7 @@ typedef struct { ...@@ -198,7 +198,7 @@ typedef struct {
uint16_t SkinTemp; uint16_t SkinTemp;
uint16_t DeviceState; uint16_t DeviceState;
uint16_t CurTemp; //[centi-Celsius] uint16_t CurTemp; //[centi-Celsius]
uint16_t spare2; uint16_t FilterAlphaValue;
uint16_t AverageGfxclkFrequency; uint16_t AverageGfxclkFrequency;
uint16_t AverageFclkFrequency; uint16_t AverageFclkFrequency;
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#define SMU13_DRIVER_IF_VERSION_YELLOW_CARP 0x04 #define SMU13_DRIVER_IF_VERSION_YELLOW_CARP 0x04
#define SMU13_DRIVER_IF_VERSION_ALDE 0x08 #define SMU13_DRIVER_IF_VERSION_ALDE 0x08
#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_0 0x37 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_0 0x37
#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x07 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x08
#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04
#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_10 0x32 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_10 0x32
#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_7 0x37 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_7 0x37
......
...@@ -2143,16 +2143,9 @@ static int sienna_cichlid_set_default_od_settings(struct smu_context *smu) ...@@ -2143,16 +2143,9 @@ static int sienna_cichlid_set_default_od_settings(struct smu_context *smu)
(OverDriveTable_t *)smu->smu_table.boot_overdrive_table; (OverDriveTable_t *)smu->smu_table.boot_overdrive_table;
OverDriveTable_t *user_od_table = OverDriveTable_t *user_od_table =
(OverDriveTable_t *)smu->smu_table.user_overdrive_table; (OverDriveTable_t *)smu->smu_table.user_overdrive_table;
OverDriveTable_t user_od_table_bak;
int ret = 0; int ret = 0;
/*
* For S3/S4/Runpm resume, no need to setup those overdrive tables again as
* - either they already have the default OD settings got during cold bootup
* - or they have some user customized OD settings which cannot be overwritten
*/
if (smu->adev->in_suspend)
return 0;
ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE,
0, (void *)boot_od_table, false); 0, (void *)boot_od_table, false);
if (ret) { if (ret) {
...@@ -2163,7 +2156,23 @@ static int sienna_cichlid_set_default_od_settings(struct smu_context *smu) ...@@ -2163,7 +2156,23 @@ static int sienna_cichlid_set_default_od_settings(struct smu_context *smu)
sienna_cichlid_dump_od_table(smu, boot_od_table); sienna_cichlid_dump_od_table(smu, boot_od_table);
memcpy(od_table, boot_od_table, sizeof(OverDriveTable_t)); memcpy(od_table, boot_od_table, sizeof(OverDriveTable_t));
memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t));
/*
* For S3/S4/Runpm resume, we need to setup those overdrive tables again,
* but we have to preserve user defined values in "user_od_table".
*/
if (!smu->adev->in_suspend) {
memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t));
smu->user_dpm_profile.user_od = false;
} else if (smu->user_dpm_profile.user_od) {
memcpy(&user_od_table_bak, user_od_table, sizeof(OverDriveTable_t));
memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t));
user_od_table->GfxclkFmin = user_od_table_bak.GfxclkFmin;
user_od_table->GfxclkFmax = user_od_table_bak.GfxclkFmax;
user_od_table->UclkFmin = user_od_table_bak.UclkFmin;
user_od_table->UclkFmax = user_od_table_bak.UclkFmax;
user_od_table->VddGfxOffset = user_od_table_bak.VddGfxOffset;
}
return 0; return 0;
} }
...@@ -2373,6 +2382,20 @@ static int sienna_cichlid_od_edit_dpm_table(struct smu_context *smu, ...@@ -2373,6 +2382,20 @@ static int sienna_cichlid_od_edit_dpm_table(struct smu_context *smu,
return ret; return ret;
} }
static int sienna_cichlid_restore_user_od_settings(struct smu_context *smu)
{
struct smu_table_context *table_context = &smu->smu_table;
OverDriveTable_t *od_table = table_context->overdrive_table;
OverDriveTable_t *user_od_table = table_context->user_overdrive_table;
int res;
res = smu_v11_0_restore_user_od_settings(smu);
if (res == 0)
memcpy(od_table, user_od_table, sizeof(OverDriveTable_t));
return res;
}
static int sienna_cichlid_run_btc(struct smu_context *smu) static int sienna_cichlid_run_btc(struct smu_context *smu)
{ {
int res; int res;
...@@ -4400,7 +4423,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { ...@@ -4400,7 +4423,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
.set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
.set_default_od_settings = sienna_cichlid_set_default_od_settings, .set_default_od_settings = sienna_cichlid_set_default_od_settings,
.od_edit_dpm_table = sienna_cichlid_od_edit_dpm_table, .od_edit_dpm_table = sienna_cichlid_od_edit_dpm_table,
.restore_user_od_settings = smu_v11_0_restore_user_od_settings, .restore_user_od_settings = sienna_cichlid_restore_user_od_settings,
.run_btc = sienna_cichlid_run_btc, .run_btc = sienna_cichlid_run_btc,
.set_power_source = smu_v11_0_set_power_source, .set_power_source = smu_v11_0_set_power_source,
.get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment