Merge tag 'amd-drm-next-5.15-2021-07-29' of https://gitlab.freedesktop.org/agd5f...
authorDave Airlie <airlied@redhat.com>
Fri, 30 Jul 2021 06:48:35 +0000 (16:48 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 30 Jul 2021 06:48:35 +0000 (16:48 +1000)
amd-drm-next-5.15-2021-07-29:

amdgpu:
- VCN/JPEG power down sequencing fixes
- Various navi pcie link handling fixes
- Clockgating fixes
- Yellow Carp fixes
- Beige Goby fixes
- Misc code cleanups
- S0ix fixes
- SMU i2c bus rework
- EEPROM handling rework
- PSP ucode handling cleanup
- SMU error handling rework
- AMD HDMI freesync fixes
- USB PD firmware update rework
- MMIO based vram access rework
- Misc display fixes
- Backlight fixes
- Add initial Cyan Skillfish support
- Overclocking fixes suspend/resume

amdkfd:
- Sysfs leak fix
- Add counters for vm faults and migration
- GPUVM TLB optimizations

radeon:
- Misc fixes

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210730033455.3852-1-alexander.deucher@amd.com
164 files changed:
MAINTAINERS
drivers/gpu/drm/amd/amdgpu/Makefile
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c [new file with mode: 0644]
drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h [new file with mode: 0644]
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
drivers/gpu/drm/amd/amdgpu/cyan_skillfish_reg_init.c [new file with mode: 0644]
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c
drivers/gpu/drm/amd/amdgpu/nv.c
drivers/gpu/drm/amd/amdgpu/nv.h
drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.c [new file with mode: 0644]
drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.h [new file with mode: 0644]
drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/amdgpu/soc15_common.h
drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h
drivers/gpu/drm/amd/amdgpu/umc_v6_7.c
drivers/gpu/drm/amd/amdgpu/umc_v6_7.h
drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
drivers/gpu/drm/amd/amdkfd/kfd_crat.c
drivers/gpu/drm/amd/amdkfd/kfd_device.c
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c
drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c
drivers/gpu/drm/amd/amdkfd/kfd_priv.h
drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h
drivers/gpu/drm/amd/amdkfd/kfd_topology.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/dcn301_smu.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c
drivers/gpu/drm/amd/display/dc/core/dc_stat.c
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dc_dp_types.h
drivers/gpu/drm/amd/display/dc/dc_stat.h
drivers/gpu/drm/amd/display/dc/dc_types.h
drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.h
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c
drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h
drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h
drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c
drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h
drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h
drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
drivers/gpu/drm/amd/display/dc/inc/link_dpcd.h
drivers/gpu/drm/amd/display/dc/irq_types.h
drivers/gpu/drm/amd/display/dmub/dmub_srv.h
drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h
drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c
drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h
drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c
drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h
drivers/gpu/drm/amd/include/amd_shared.h
drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h
drivers/gpu/drm/amd/include/asic_reg/mp/mp_11_0_8_offset.h [new file with mode: 0644]
drivers/gpu/drm/amd/include/asic_reg/umc/umc_8_7_0_sh_mask.h
drivers/gpu/drm/amd/include/cyan_skillfish_ip_offset.h [new file with mode: 0644]
drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h [new file with mode: 0644]
drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h
drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
drivers/gpu/drm/amd/pm/inc/smu_v11_8_pmfw.h [new file with mode: 0644]
drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h [new file with mode: 0644]
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile
drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c [new file with mode: 0644]
drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.h [new file with mode: 0644]
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
include/drm/amd_asic_type.h

index dde565a88c87796c1ae782b4cb705f46c679ea28..851255b71cccd18f69890243e19b6c242176c9f7 100644 (file)
@@ -15481,6 +15481,8 @@ M:      Pan, Xinhui <Xinhui.Pan@amd.com>
 L:     amd-gfx@lists.freedesktop.org
 S:     Supported
 T:     git https://gitlab.freedesktop.org/agd5f/linux.git
+B:     https://gitlab.freedesktop.org/drm/amd/-/issues
+C:     irc://irc.oftc.net/radeon
 F:     drivers/gpu/drm/amd/
 F:     drivers/gpu/drm/radeon/
 F:     include/uapi/drm/amdgpu_drm.h
index c56320e78c0e1fd490a77b4225ba45fbde188032..f089794bbdd5b6e42acc521e3e606bb2ea3099ab 100644 (file)
@@ -57,7 +57,8 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
        amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \
        amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \
        amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \
-       amdgpu_fw_attestation.o amdgpu_securedisplay.o amdgpu_hdp.o
+       amdgpu_fw_attestation.o amdgpu_securedisplay.o amdgpu_hdp.o \
+       amdgpu_eeprom.o
 
 amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o
 
@@ -75,7 +76,7 @@ amdgpu-y += \
        vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o navi10_reg_init.o navi14_reg_init.o \
        arct_reg_init.o navi12_reg_init.o mxgpu_nv.o sienna_cichlid_reg_init.o vangogh_reg_init.o \
        nbio_v7_2.o dimgrey_cavefish_reg_init.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o \
-       beige_goby_reg_init.o yellow_carp_reg_init.o
+       beige_goby_reg_init.o yellow_carp_reg_init.o cyan_skillfish_reg_init.o
 
 # add DF block
 amdgpu-y += \
@@ -111,6 +112,7 @@ amdgpu-y += \
        psp_v3_1.o \
        psp_v10_0.o \
        psp_v11_0.o \
+       psp_v11_0_8.o \
        psp_v12_0.o \
        psp_v13_0.o
 
index 8ac6eb9f1fdb8af08b4f510da6d748f150b6e7d9..d10baa3338bc48d2dc6c39d01ef731ee5fc3a1ff 100644 (file)
@@ -1108,8 +1108,13 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev);
 
 int amdgpu_gpu_wait_for_idle(struct amdgpu_device *adev);
 
+void amdgpu_device_mm_access(struct amdgpu_device *adev, loff_t pos,
+                            void *buf, size_t size, bool write);
+size_t amdgpu_device_aper_access(struct amdgpu_device *adev, loff_t pos,
+                                void *buf, size_t size, bool write);
+
 void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
-                              uint32_t *buf, size_t size, bool write);
+                              void *buf, size_t size, bool write);
 uint32_t amdgpu_device_rreg(struct amdgpu_device *adev,
                            uint32_t reg, uint32_t acc_flags);
 void amdgpu_device_wreg(struct amdgpu_device *adev,
@@ -1385,12 +1390,12 @@ int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_sta
 int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev);
 
 void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps);
-bool amdgpu_acpi_is_s0ix_supported(struct amdgpu_device *adev);
+bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev);
 void amdgpu_acpi_detect(void);
 #else
 static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; }
 static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { }
-static inline bool amdgpu_acpi_is_s0ix_supported(struct amdgpu_device *adev) { return false; }
+static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; }
 static inline void amdgpu_acpi_detect(void) { }
 static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; }
 static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev,
index b8655ff73a658a662a763d3a3e85bf7bc69c1552..cc9c9f8b23b2cbb48f19e517bd6b069413caeb98 100644 (file)
@@ -160,17 +160,28 @@ static int acp_poweron(struct generic_pm_domain *genpd)
        return 0;
 }
 
-static struct device *get_mfd_cell_dev(const char *device_name, int r)
+static int acp_genpd_add_device(struct device *dev, void *data)
 {
-       char auto_dev_name[25];
-       struct device *dev;
+       struct generic_pm_domain *gpd = data;
+       int ret;
 
-       snprintf(auto_dev_name, sizeof(auto_dev_name),
-                "%s.%d.auto", device_name, r);
-       dev = bus_find_device_by_name(&platform_bus_type, NULL, auto_dev_name);
-       dev_info(dev, "device %s added to pm domain\n", auto_dev_name);
+       ret = pm_genpd_add_device(gpd, dev);
+       if (ret)
+               dev_err(dev, "Failed to add dev to genpd %d\n", ret);
 
-       return dev;
+       return ret;
+}
+
+static int acp_genpd_remove_device(struct device *dev, void *data)
+{
+       int ret;
+
+       ret = pm_genpd_remove_device(dev);
+       if (ret)
+               dev_err(dev, "Failed to remove dev from genpd %d\n", ret);
+
+       /* Continue to remove */
+       return 0;
 }
 
 /**
@@ -181,11 +192,10 @@ static struct device *get_mfd_cell_dev(const char *device_name, int r)
  */
 static int acp_hw_init(void *handle)
 {
-       int r, i;
+       int r;
        uint64_t acp_base;
        u32 val = 0;
        u32 count = 0;
-       struct device *dev;
        struct i2s_platform_data *i2s_pdata = NULL;
 
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -341,15 +351,10 @@ static int acp_hw_init(void *handle)
        if (r)
                goto failure;
 
-       for (i = 0; i < ACP_DEVS ; i++) {
-               dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i);
-               r = pm_genpd_add_device(&adev->acp.acp_genpd->gpd, dev);
-               if (r) {
-                       dev_err(dev, "Failed to add dev to genpd\n");
-                       goto failure;
-               }
-       }
-
+       r = device_for_each_child(adev->acp.parent, &adev->acp.acp_genpd->gpd,
+                                 acp_genpd_add_device);
+       if (r)
+               goto failure;
 
        /* Assert Soft reset of ACP */
        val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
@@ -410,10 +415,8 @@ failure:
  */
 static int acp_hw_fini(void *handle)
 {
-       int i, ret;
        u32 val = 0;
        u32 count = 0;
-       struct device *dev;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
        /* return early if no ACP */
@@ -458,13 +461,8 @@ static int acp_hw_fini(void *handle)
                udelay(100);
        }
 
-       for (i = 0; i < ACP_DEVS ; i++) {
-               dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i);
-               ret = pm_genpd_remove_device(dev);
-               /* If removal fails, dont giveup and try rest */
-               if (ret)
-                       dev_err(dev, "remove dev from genpd failed\n");
-       }
+       device_for_each_child(adev->acp.parent, NULL,
+                             acp_genpd_remove_device);
 
        mfd_remove_devices(adev->acp.parent);
        kfree(adev->acp.acp_res);
index 84a1b4bc9bb4dc74a5260e0c6a598a994ca07540..58520b0ad0bfb921d40a54128274e690f19c1aa7 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/power_supply.h>
 #include <linux/pm_runtime.h>
+#include <linux/suspend.h>
 #include <acpi/video.h>
 #include <acpi/actbl.h>
 
@@ -853,8 +854,8 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
                if (amdgpu_device_has_dc_support(adev)) {
 #if defined(CONFIG_DRM_AMD_DC)
                        struct amdgpu_display_manager *dm = &adev->dm;
-                       if (dm->backlight_dev)
-                               atif->bd = dm->backlight_dev;
+                       if (dm->backlight_dev[0])
+                               atif->bd = dm->backlight_dev[0];
 #endif
                } else {
                        struct drm_encoder *tmp;
@@ -1031,18 +1032,18 @@ void amdgpu_acpi_detect(void)
 }
 
 /**
- * amdgpu_acpi_is_s0ix_supported
+ * amdgpu_acpi_is_s0ix_active
  *
  * @adev: amdgpu_device_pointer
  *
  * returns true if supported, false if not.
  */
-bool amdgpu_acpi_is_s0ix_supported(struct amdgpu_device *adev)
+bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev)
 {
 #if defined(CONFIG_AMD_PMC) || defined(CONFIG_AMD_PMC_MODULE)
        if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) {
                if (adev->flags & AMD_IS_APU)
-                       return true;
+                       return pm_suspend_target_state == PM_SUSPEND_TO_IDLE;
        }
 #endif
        return false;
index f9c01bdc3d4c77cc9f25a932e4dc6354b24d47e2..7b46ba551cb208e638f6b930ff4e5bbbd1957796 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include "amdgpu_amdkfd.h"
+#include "amd_pcie.h"
 #include "amd_shared.h"
 
 #include "amdgpu.h"
@@ -553,6 +554,88 @@ uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *s
        return  (uint8_t)ret;
 }
 
+int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct kgd_dev *dst, struct kgd_dev *src, bool is_min)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)dst, *peer_adev;
+       int num_links;
+
+       if (adev->asic_type != CHIP_ALDEBARAN)
+               return 0;
+
+       if (src)
+               peer_adev = (struct amdgpu_device *)src;
+
+       /* num links returns 0 for indirect peers since indirect route is unknown. */
+       num_links = is_min ? 1 : amdgpu_xgmi_get_num_links(adev, peer_adev);
+       if (num_links < 0) {
+               DRM_ERROR("amdgpu: failed to get xgmi num links between node %d and %d. ret = %d\n",
+                       adev->gmc.xgmi.physical_node_id,
+                       peer_adev->gmc.xgmi.physical_node_id, num_links);
+               num_links = 0;
+       }
+
+       /* Aldebaran xGMI DPM is defeatured so assume x16 x 25Gbps for bandwidth. */
+       return (num_links * 16 * 25000)/BITS_PER_BYTE;
+}
+
+int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct kgd_dev *dev, bool is_min)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)dev;
+       int num_lanes_shift = (is_min ? ffs(adev->pm.pcie_mlw_mask) :
+                                                       fls(adev->pm.pcie_mlw_mask)) - 1;
+       int gen_speed_shift = (is_min ? ffs(adev->pm.pcie_gen_mask &
+                                               CAIL_PCIE_LINK_SPEED_SUPPORT_MASK) :
+                                       fls(adev->pm.pcie_gen_mask &
+                                               CAIL_PCIE_LINK_SPEED_SUPPORT_MASK)) - 1;
+       uint32_t num_lanes_mask = 1 << num_lanes_shift;
+       uint32_t gen_speed_mask = 1 << gen_speed_shift;
+       int num_lanes_factor = 0, gen_speed_mbits_factor = 0;
+
+       switch (num_lanes_mask) {
+       case CAIL_PCIE_LINK_WIDTH_SUPPORT_X1:
+               num_lanes_factor = 1;
+               break;
+       case CAIL_PCIE_LINK_WIDTH_SUPPORT_X2:
+               num_lanes_factor = 2;
+               break;
+       case CAIL_PCIE_LINK_WIDTH_SUPPORT_X4:
+               num_lanes_factor = 4;
+               break;
+       case CAIL_PCIE_LINK_WIDTH_SUPPORT_X8:
+               num_lanes_factor = 8;
+               break;
+       case CAIL_PCIE_LINK_WIDTH_SUPPORT_X12:
+               num_lanes_factor = 12;
+               break;
+       case CAIL_PCIE_LINK_WIDTH_SUPPORT_X16:
+               num_lanes_factor = 16;
+               break;
+       case CAIL_PCIE_LINK_WIDTH_SUPPORT_X32:
+               num_lanes_factor = 32;
+               break;
+       }
+
+       switch (gen_speed_mask) {
+       case CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1:
+               gen_speed_mbits_factor = 2500;
+               break;
+       case CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2:
+               gen_speed_mbits_factor = 5000;
+               break;
+       case CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3:
+               gen_speed_mbits_factor = 8000;
+               break;
+       case CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4:
+               gen_speed_mbits_factor = 16000;
+               break;
+       case CAIL_PCIE_LINK_SPEED_SUPPORT_GEN5:
+               gen_speed_mbits_factor = 32000;
+               break;
+       }
+
+       return (num_lanes_factor * gen_speed_mbits_factor)/BITS_PER_BYTE;
+}
+
 uint64_t amdgpu_amdkfd_get_mmio_remap_phys_addr(struct kgd_dev *kgd)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
index cf62f43a03da1d5eb4eb635b64ffa2913c77d9a1..0462d4aceab7bcf44b905b792a33110db891fbda 100644 (file)
@@ -226,6 +226,8 @@ uint32_t amdgpu_amdkfd_get_num_gws(struct kgd_dev *kgd);
 uint32_t amdgpu_amdkfd_get_asic_rev_id(struct kgd_dev *kgd);
 int amdgpu_amdkfd_get_noretry(struct kgd_dev *kgd);
 uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *src);
+int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct kgd_dev *dst, struct kgd_dev *src, bool is_min);
+int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct kgd_dev *dev, bool is_min);
 
 /* Read user wptr from a specified user address space with page fault
  * disabled. The memory must be pinned and mapped to the hardware when
@@ -330,7 +332,7 @@ int kgd2kfd_pre_reset(struct kfd_dev *kfd);
 int kgd2kfd_post_reset(struct kfd_dev *kfd);
 void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry);
 void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd);
-void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask);
+void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask);
 #else
 static inline int kgd2kfd_init(void)
 {
@@ -389,7 +391,7 @@ void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd)
 }
 
 static inline
-void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask)
+void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask)
 {
 }
 #endif
index 4fb15750b9bb4c682ba00ae933a6001545216671..c4b3eeeab0a199342d3118cb429cb2ba5b005edc 100644 (file)
@@ -1285,11 +1285,22 @@ int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct kgd_dev *kgd,
        if (avm->process_info)
                return -EINVAL;
 
+       /* Free the original amdgpu allocated pasid,
+        * will be replaced with kfd allocated pasid.
+        */
+       if (avm->pasid) {
+               amdgpu_pasid_free(avm->pasid);
+               amdgpu_vm_set_pasid(adev, avm, 0);
+       }
+
        /* Convert VM into a compute VM */
-       ret = amdgpu_vm_make_compute(adev, avm, pasid);
+       ret = amdgpu_vm_make_compute(adev, avm);
        if (ret)
                return ret;
 
+       ret = amdgpu_vm_set_pasid(adev, avm, pasid);
+       if (ret)
+               return ret;
        /* Initialize KFD part of the VM and process info */
        ret = init_kfd_vm(avm, process_info, ef);
        if (ret)
index 8398daa0c06a0b5b9422cf47dbe6efd08b64f86b..6ca9fe54ee0af42429af49d52b58003ad80a71fb 100644 (file)
@@ -116,6 +116,7 @@ const char *amdgpu_asic_name[] = {
        "RENOIR",
        "ALDEBARAN",
        "NAVI10",
+       "CYAN_SKILLFISH",
        "NAVI14",
        "NAVI12",
        "SIENNA_CICHLID",
@@ -287,7 +288,7 @@ bool amdgpu_device_supports_smart_shift(struct drm_device *dev)
  */
 
 /**
- * amdgpu_device_vram_access - read/write a buffer in vram
+ * amdgpu_device_mm_access - access vram by MM_INDEX/MM_DATA
  *
  * @adev: amdgpu_device pointer
  * @pos: offset of the buffer in vram
@@ -295,22 +296,65 @@ bool amdgpu_device_supports_smart_shift(struct drm_device *dev)
  * @size: read/write size, sizeof(@buf) must > @size
  * @write: true - write to vram, otherwise - read from vram
  */
-void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
-                              uint32_t *buf, size_t size, bool write)
+void amdgpu_device_mm_access(struct amdgpu_device *adev, loff_t pos,
+                            void *buf, size_t size, bool write)
 {
        unsigned long flags;
-       uint32_t hi = ~0;
+       uint32_t hi = ~0, tmp = 0;
+       uint32_t *data = buf;
        uint64_t last;
        int idx;
 
        if (!drm_dev_enter(&adev->ddev, &idx))
                return;
 
+       BUG_ON(!IS_ALIGNED(pos, 4) || !IS_ALIGNED(size, 4));
+
+       spin_lock_irqsave(&adev->mmio_idx_lock, flags);
+       for (last = pos + size; pos < last; pos += 4) {
+               tmp = pos >> 31;
+
+               WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)pos) | 0x80000000);
+               if (tmp != hi) {
+                       WREG32_NO_KIQ(mmMM_INDEX_HI, tmp);
+                       hi = tmp;
+               }
+               if (write)
+                       WREG32_NO_KIQ(mmMM_DATA, *data++);
+               else
+                       *data++ = RREG32_NO_KIQ(mmMM_DATA);
+       }
+
+       spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
+       drm_dev_exit(idx);
+}
+
+/**
+ * amdgpu_device_vram_access - access vram by vram aperature
+ *
+ * @adev: amdgpu_device pointer
+ * @pos: offset of the buffer in vram
+ * @buf: virtual address of the buffer in system memory
+ * @size: read/write size, sizeof(@buf) must > @size
+ * @write: true - write to vram, otherwise - read from vram
+ *
+ * The return value means how many bytes have been transferred.
+ */
+size_t amdgpu_device_aper_access(struct amdgpu_device *adev, loff_t pos,
+                                void *buf, size_t size, bool write)
+{
 #ifdef CONFIG_64BIT
+       void __iomem *addr;
+       size_t count = 0;
+       uint64_t last;
+
+       if (!adev->mman.aper_base_kaddr)
+               return 0;
+
        last = min(pos + size, adev->gmc.visible_vram_size);
        if (last > pos) {
-               void __iomem *addr = adev->mman.aper_base_kaddr + pos;
-               size_t count = last - pos;
+               addr = adev->mman.aper_base_kaddr + pos;
+               count = last - pos;
 
                if (write) {
                        memcpy_toio(addr, buf, count);
@@ -322,35 +366,37 @@ void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
                        memcpy_fromio(buf, addr, count);
                }
 
-               if (count == size)
-                       goto exit;
-
-               pos += count;
-               buf += count / 4;
-               size -= count;
        }
+
+       return count;
+#else
+       return 0;
 #endif
+}
 
-       spin_lock_irqsave(&adev->mmio_idx_lock, flags);
-       for (last = pos + size; pos < last; pos += 4) {
-               uint32_t tmp = pos >> 31;
+/**
+ * amdgpu_device_vram_access - read/write a buffer in vram
+ *
+ * @adev: amdgpu_device pointer
+ * @pos: offset of the buffer in vram
+ * @buf: virtual address of the buffer in system memory
+ * @size: read/write size, sizeof(@buf) must > @size
+ * @write: true - write to vram, otherwise - read from vram
+ */
+void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
+                              void *buf, size_t size, bool write)
+{
+       size_t count;
 
-               WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)pos) | 0x80000000);
-               if (tmp != hi) {
-                       WREG32_NO_KIQ(mmMM_INDEX_HI, tmp);
-                       hi = tmp;
-               }
-               if (write)
-                       WREG32_NO_KIQ(mmMM_DATA, *buf++);
-               else
-                       *buf++ = RREG32_NO_KIQ(mmMM_DATA);
+       /* try to using vram apreature to access vram first */
+       count = amdgpu_device_aper_access(adev, pos, buf, size, write);
+       size -= count;
+       if (size) {
+               /* using MM to access rest vram */
+               pos += count;
+               buf += count;
+               amdgpu_device_mm_access(adev, pos, buf, size, write);
        }
-       spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
-
-#ifdef CONFIG_64BIT
-exit:
-#endif
-       drm_dev_exit(idx);
 }
 
 /*
@@ -518,7 +564,7 @@ void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
            adev->gfx.rlc.funcs &&
            adev->gfx.rlc.funcs->is_rlcg_access_range) {
                if (adev->gfx.rlc.funcs->is_rlcg_access_range(adev, reg))
-                       return adev->gfx.rlc.funcs->rlcg_wreg(adev, reg, v, 0, 0);
+                       return adev->gfx.rlc.funcs->sriov_wreg(adev, reg, v, 0, 0);
        } else {
                writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
        }
@@ -1395,6 +1441,10 @@ static int amdgpu_device_init_apu_flags(struct amdgpu_device *adev)
                break;
        case CHIP_YELLOW_CARP:
                break;
+       case CHIP_CYAN_SKILLFISH:
+               if (adev->pdev->device == 0x13FE)
+                       adev->apu_flags |= AMD_APU_IS_CYAN_SKILLFISH2;
+               break;
        default:
                return -EINVAL;
        }
@@ -2101,6 +2151,7 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
        case  CHIP_BEIGE_GOBY:
        case CHIP_VANGOGH:
        case CHIP_YELLOW_CARP:
+       case CHIP_CYAN_SKILLFISH:
                if (adev->asic_type == CHIP_VANGOGH)
                        adev->family = AMDGPU_FAMILY_VGH;
                else if (adev->asic_type == CHIP_YELLOW_CARP)
@@ -3505,13 +3556,13 @@ int amdgpu_device_init(struct amdgpu_device *adev,
        r = amdgpu_device_get_job_timeout_settings(adev);
        if (r) {
                dev_err(adev->dev, "invalid lockup_timeout parameter syntax\n");
-               goto failed_unmap;
+               return r;
        }
 
        /* early init functions */
        r = amdgpu_device_ip_early_init(adev);
        if (r)
-               goto failed_unmap;
+               return r;
 
        /* doorbell bar mapping and doorbell index init*/
        amdgpu_device_doorbell_init(adev);
@@ -3625,6 +3676,8 @@ fence_driver_init:
                goto release_ras_con;
        }
 
+       amdgpu_fence_driver_hw_init(adev);
+
        dev_info(adev->dev,
                "SE %d, SH per SE %d, CU per SH %d, active_cu_number %d\n",
                        adev->gfx.config.max_shader_engines,
@@ -3737,10 +3790,6 @@ release_ras_con:
 failed:
        amdgpu_vf_error_trans_all(adev);
 
-failed_unmap:
-       iounmap(adev->rmmio);
-       adev->rmmio = NULL;
-
        return r;
 }
 
@@ -3796,7 +3845,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
                else
                        drm_atomic_helper_shutdown(adev_to_drm(adev));
        }
-       amdgpu_fence_driver_fini_hw(adev);
+       amdgpu_fence_driver_hw_fini(adev);
 
        if (adev->pm_sysfs_en)
                amdgpu_pm_sysfs_fini(adev);
@@ -3818,7 +3867,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
 void amdgpu_device_fini_sw(struct amdgpu_device *adev)
 {
        amdgpu_device_ip_fini(adev);
-       amdgpu_fence_driver_fini_sw(adev);
+       amdgpu_fence_driver_sw_fini(adev);
        release_firmware(adev->firmware.gpu_info_fw);
        adev->firmware.gpu_info_fw = NULL;
        adev->accel_working = false;
@@ -3893,7 +3942,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
        /* evict vram memory */
        amdgpu_bo_evict_vram(adev);
 
-       amdgpu_fence_driver_suspend(adev);
+       amdgpu_fence_driver_hw_fini(adev);
 
        amdgpu_device_ip_suspend_phase2(adev);
        /* evict remaining vram memory
@@ -3938,7 +3987,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
                dev_err(adev->dev, "amdgpu_device_ip_resume failed (%d).\n", r);
                return r;
        }
-       amdgpu_fence_driver_resume(adev);
+       amdgpu_fence_driver_hw_init(adev);
 
 
        r = amdgpu_device_ip_late_init(adev);
@@ -4428,7 +4477,7 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
                amdgpu_fence_driver_force_completion(ring);
        }
 
-       if(job)
+       if (job && job->vm)
                drm_sched_increase_karma(&job->base);
 
        r = amdgpu_reset_prepare_hwcontext(adev, reset_context);
@@ -4892,7 +4941,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
                        DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress",
                                job ? job->base.id : -1, hive->hive_id);
                        amdgpu_put_xgmi_hive(hive);
-                       if (job)
+                       if (job && job->vm)
                                drm_sched_increase_karma(&job->base);
                        return 0;
                }
@@ -4916,7 +4965,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
                                        job ? job->base.id : -1);
 
                /* even we skipped this reset, still need to set the job to guilty */
-               if (job)
+               if (job && job->vm)
                        drm_sched_increase_karma(&job->base);
                goto skip_recovery;
        }
@@ -5283,6 +5332,10 @@ int amdgpu_device_baco_exit(struct drm_device *dev)
            adev->nbio.funcs->enable_doorbell_interrupt)
                adev->nbio.funcs->enable_doorbell_interrupt(adev, true);
 
+       if (amdgpu_passthrough(adev) &&
+           adev->nbio.funcs->clear_doorbell_interrupt)
+               adev->nbio.funcs->clear_doorbell_interrupt(adev);
+
        return 0;
 }
 
index 2bd13fc2541a79db05edd46f5c9f2529504e4a8c..d637b0536f84e67012dfea3be3e922d8d2dff235 100644 (file)
@@ -870,11 +870,10 @@ MODULE_PARM_DESC(reset_method, "GPU reset method (-1 = auto (default), 0 = legac
 module_param_named(reset_method, amdgpu_reset_method, int, 0444);
 
 /**
- * DOC: bad_page_threshold (int)
- * Bad page threshold is to specify the threshold value of faulty pages
- * detected by RAS ECC, that may result in GPU entering bad status if total
- * faulty pages by ECC exceed threshold value and leave it for user's further
- * check.
+ * DOC: bad_page_threshold (int) Bad page threshold is specifies the
+ * threshold value of faulty pages detected by RAS ECC, which may
+ * result in the GPU entering bad status when the number of total
+ * faulty pages by ECC exceeds the threshold value.
  */
 MODULE_PARM_DESC(bad_page_threshold, "Bad page threshold(-1 = auto(default value), 0 = disable bad page retirement)");
 module_param_named(bad_page_threshold, amdgpu_bad_page_threshold, int, 0444);
@@ -1213,6 +1212,9 @@ static const struct pci_device_id pciidlist[] = {
        {0x1002, 0x740F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT},
        {0x1002, 0x7410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT},
 
+       /* CYAN_SKILLFISH */
+       {0x1002, 0x13FE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
+
        {0, 0, 0}
 };
 
@@ -1467,7 +1469,7 @@ static int amdgpu_pmops_suspend(struct device *dev)
        struct amdgpu_device *adev = drm_to_adev(drm_dev);
        int r;
 
-       if (amdgpu_acpi_is_s0ix_supported(adev))
+       if (amdgpu_acpi_is_s0ix_active(adev))
                adev->in_s0ix = true;
        adev->in_s3 = true;
        r = amdgpu_device_suspend(drm_dev, true);
@@ -1483,7 +1485,7 @@ static int amdgpu_pmops_resume(struct device *dev)
        int r;
 
        r = amdgpu_device_resume(drm_dev, true);
-       if (amdgpu_acpi_is_s0ix_supported(adev))
+       if (amdgpu_acpi_is_s0ix_active(adev))
                adev->in_s0ix = false;
        return r;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
new file mode 100644 (file)
index 0000000..4d9eb01
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "amdgpu_eeprom.h"
+#include "amdgpu.h"
+
+/* AT24CM02 and M24M02-R have a 256-byte write page size.
+ */
+#define EEPROM_PAGE_BITS   8
+#define EEPROM_PAGE_SIZE   (1U << EEPROM_PAGE_BITS)
+#define EEPROM_PAGE_MASK   (EEPROM_PAGE_SIZE - 1)
+
+#define EEPROM_OFFSET_SIZE 2
+
+/* EEPROM memory addresses are 19-bits long, which can
+ * be partitioned into 3, 8, 8 bits, for a total of 19.
+ * The upper 3 bits are sent as part of the 7-bit
+ * "Device Type Identifier"--an I2C concept, which for EEPROM devices
+ * is hard-coded as 1010b, indicating that it is an EEPROM
+ * device--this is the wire format, followed by the upper
+ * 3 bits of the 19-bit address, followed by the direction,
+ * followed by two bytes holding the rest of the 16-bits of
+ * the EEPROM memory address. The format on the wire for EEPROM
+ * devices is: 1010XYZD, A15:A8, A7:A0,
+ * Where D is the direction and sequenced out by the hardware.
+ * Bits XYZ are memory address bits 18, 17 and 16.
+ * These bits are compared to how pins 1-3 of the part are connected,
+ * depending on the size of the part, more on that later.
+ *
+ * Note that of this wire format, a client is in control
+ * of, and needs to specify only XYZ, A15:A8, A7:0, bits,
+ * which is exactly the EEPROM memory address, or offset,
+ * in order to address up to 8 EEPROM devices on the I2C bus.
+ *
+ * For instance, a 2-Mbit I2C EEPROM part, addresses all its bytes,
+ * using an 18-bit address, bit 17 to 0 and thus would use all but one bit of
+ * the 19 bits previously mentioned. The designer would then not connect
+ * pins 1 and 2, and pin 3 usually named "A_2" or "E2", would be connected to
+ * either Vcc or GND. This would allow for up to two 2-Mbit parts on
+ * the same bus, where one would be addressable with bit 18 as 1, and
+ * the other with bit 18 of the address as 0.
+ *
+ * For a 2-Mbit part, bit 18 is usually known as the "Chip Enable" or
+ * "Hardware Address Bit". This bit is compared to the load on pin 3
+ * of the device, described above, and if there is a match, then this
+ * device responds to the command. This way, you can connect two
+ * 2-Mbit EEPROM devices on the same bus, but see one contiguous
+ * memory from 0 to 7FFFFh, where address 0 to 3FFFF is in the device
+ * whose pin 3 is connected to GND, and address 40000 to 7FFFFh is in
+ * the 2nd device, whose pin 3 is connected to Vcc.
+ *
+ * This addressing you encode in the 32-bit "eeprom_addr" below,
+ * namely the 19-bits "XYZ,A15:A0", as a single 19-bit address. For
+ * instance, eeprom_addr = 0x6DA01, is 110_1101_1010_0000_0001, where
+ * XYZ=110b, and A15:A0=DA01h. The XYZ bits become part of the device
+ * address, and the rest of the address bits are sent as the memory
+ * address bytes.
+ *
+ * That is, for an I2C EEPROM driver everything is controlled by
+ * the "eeprom_addr".
+ *
+ * P.S. If you need to write, lock and read the Identification Page,
+ * (M24M02-DR device only, which we do not use), change the "7" to
+ * "0xF" in the macro below, and let the client set bit 20 to 1 in
+ * "eeprom_addr", and set A10 to 0 to write into it, and A10 and A1 to
+ * 1 to lock it permanently.
+ */
+#define MAKE_I2C_ADDR(_aa) ((0xA << 3) | (((_aa) >> 16) & 7))
+
+static int __amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap, u32 eeprom_addr,
+                               u8 *eeprom_buf, u16 buf_size, bool read)
+{
+       u8 eeprom_offset_buf[EEPROM_OFFSET_SIZE];
+       struct i2c_msg msgs[] = {
+               {
+                       .flags = 0,
+                       .len = EEPROM_OFFSET_SIZE,
+                       .buf = eeprom_offset_buf,
+               },
+               {
+                       .flags = read ? I2C_M_RD : 0,
+               },
+       };
+       const u8 *p = eeprom_buf;
+       int r;
+       u16 len;
+
+       for (r = 0; buf_size > 0;
+             buf_size -= len, eeprom_addr += len, eeprom_buf += len) {
+               /* Set the EEPROM address we want to write to/read from.
+                */
+               msgs[0].addr = MAKE_I2C_ADDR(eeprom_addr);
+               msgs[1].addr = msgs[0].addr;
+               msgs[0].buf[0] = (eeprom_addr >> 8) & 0xff;
+               msgs[0].buf[1] = eeprom_addr & 0xff;
+
+               if (!read) {
+                       /* Write the maximum amount of data, without
+                        * crossing the device's page boundary, as per
+                        * its spec. Partial page writes are allowed,
+                        * starting at any location within the page,
+                        * so long as the page boundary isn't crossed
+                        * over (actually the page pointer rolls
+                        * over).
+                        *
+                        * As per the AT24CM02 EEPROM spec, after
+                        * writing into a page, the I2C driver should
+                        * terminate the transfer, i.e. in
+                        * "i2c_transfer()" below, with a STOP
+                        * condition, so that the self-timed write
+                        * cycle begins. This is implied for the
+                        * "i2c_transfer()" abstraction.
+                        */
+                       len = min(EEPROM_PAGE_SIZE - (eeprom_addr &
+                                                     EEPROM_PAGE_MASK),
+                                 (u32)buf_size);
+               } else {
+                       /* Reading from the EEPROM has no limitation
+                        * on the number of bytes read from the EEPROM
+                        * device--they are simply sequenced out.
+                        */
+                       len = buf_size;
+               }
+               msgs[1].len = len;
+               msgs[1].buf = eeprom_buf;
+
+               /* This constitutes a START-STOP transaction.
+                */
+               r = i2c_transfer(i2c_adap, msgs, ARRAY_SIZE(msgs));
+               if (r != ARRAY_SIZE(msgs))
+                       break;
+
+               if (!read) {
+                       /* According to EEPROM specs the length of the
+                        * self-writing cycle, tWR (tW), is 10 ms.
+                        *
+                        * TODO: Use polling on ACK, aka Acknowledge
+                        * Polling, to minimize waiting for the
+                        * internal write cycle to complete, as it is
+                        * usually smaller than tWR (tW).
+                        */
+                       msleep(10);
+               }
+       }
+
+       return r < 0 ? r : eeprom_buf - p;
+}
+
+/**
+ * amdgpu_eeprom_xfer -- Read/write from/to an I2C EEPROM device
+ * @i2c_adap: pointer to the I2C adapter to use
+ * @eeprom_addr: EEPROM address from which to read/write
+ * @eeprom_buf: pointer to data buffer to read into/write from
+ * @buf_size: the size of @eeprom_buf
+ * @read: True if reading from the EEPROM, false if writing
+ *
+ * Returns the number of bytes read/written; -errno on error.
+ */
+static int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap, u32 eeprom_addr,
+                             u8 *eeprom_buf, u16 buf_size, bool read)
+{
+       const struct i2c_adapter_quirks *quirks = i2c_adap->quirks;
+       u16 limit;
+
+       if (!quirks)
+               limit = 0;
+       else if (read)
+               limit = quirks->max_read_len;
+       else
+               limit = quirks->max_write_len;
+
+       if (limit == 0) {
+               return __amdgpu_eeprom_xfer(i2c_adap, eeprom_addr,
+                                           eeprom_buf, buf_size, read);
+       } else if (limit <= EEPROM_OFFSET_SIZE) {
+               dev_err_ratelimited(&i2c_adap->dev,
+                                   "maddr:0x%04X size:0x%02X:quirk max_%s_len must be > %d",
+                                   eeprom_addr, buf_size,
+                                   read ? "read" : "write", EEPROM_OFFSET_SIZE);
+               return -EINVAL;
+       } else {
+               u16 ps; /* Partial size */
+               int res = 0, r;
+
+               /* The "limit" includes all data bytes sent/received,
+                * which would include the EEPROM_OFFSET_SIZE bytes.
+                * Account for them here.
+                */
+               limit -= EEPROM_OFFSET_SIZE;
+               for ( ; buf_size > 0;
+                     buf_size -= ps, eeprom_addr += ps, eeprom_buf += ps) {
+                       ps = min(limit, buf_size);
+
+                       r = __amdgpu_eeprom_xfer(i2c_adap, eeprom_addr,
+                                                eeprom_buf, ps, read);
+                       if (r < 0)
+                               return r;
+                       res += r;
+               }
+
+               return res;
+       }
+}
+
+int amdgpu_eeprom_read(struct i2c_adapter *i2c_adap,
+                      u32 eeprom_addr, u8 *eeprom_buf,
+                      u16 bytes)
+{
+       return amdgpu_eeprom_xfer(i2c_adap, eeprom_addr, eeprom_buf, bytes,
+                                 true);
+}
+
+int amdgpu_eeprom_write(struct i2c_adapter *i2c_adap,
+                       u32 eeprom_addr, u8 *eeprom_buf,
+                       u16 bytes)
+{
+       return amdgpu_eeprom_xfer(i2c_adap, eeprom_addr, eeprom_buf, bytes,
+                                 false);
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h
new file mode 100644 (file)
index 0000000..6935adb
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _AMDGPU_EEPROM_H
+#define _AMDGPU_EEPROM_H
+
+#include <linux/i2c.h>
+
+int amdgpu_eeprom_read(struct i2c_adapter *i2c_adap,
+                      u32 eeprom_addr, u8 *eeprom_buf,
+                      u16 bytes);
+
+int amdgpu_eeprom_write(struct i2c_adapter *i2c_adap,
+                       u32 eeprom_addr, u8 *eeprom_buf,
+                       u16 bytes);
+
+#endif
index d4547d19517378fadc207e1cf26aab99f2a1d822..0b1c48590c436a8e12b345394fe8cce5bf857ba2 100644 (file)
@@ -417,9 +417,6 @@ int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
        }
        amdgpu_fence_write(ring, atomic_read(&ring->fence_drv.last_seq));
 
-       if (irq_src)
-               amdgpu_irq_get(adev, irq_src, irq_type);
-
        ring->fence_drv.irq_src = irq_src;
        ring->fence_drv.irq_type = irq_type;
        ring->fence_drv.initialized = true;
@@ -525,7 +522,7 @@ int amdgpu_fence_driver_init(struct amdgpu_device *adev)
  *
  * Tear down the fence driver for all possible rings (all asics).
  */
-void amdgpu_fence_driver_fini_hw(struct amdgpu_device *adev)
+void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev)
 {
        int i, r;
 
@@ -553,7 +550,7 @@ void amdgpu_fence_driver_fini_hw(struct amdgpu_device *adev)
        }
 }
 
-void amdgpu_fence_driver_fini_sw(struct amdgpu_device *adev)
+void amdgpu_fence_driver_sw_fini(struct amdgpu_device *adev)
 {
        unsigned int i, j;
 
@@ -572,49 +569,18 @@ void amdgpu_fence_driver_fini_sw(struct amdgpu_device *adev)
 }
 
 /**
- * amdgpu_fence_driver_suspend - suspend the fence driver
- * for all possible rings.
- *
- * @adev: amdgpu device pointer
- *
- * Suspend the fence driver for all possible rings (all asics).
- */
-void amdgpu_fence_driver_suspend(struct amdgpu_device *adev)
-{
-       int i, r;
-
-       for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
-               struct amdgpu_ring *ring = adev->rings[i];
-               if (!ring || !ring->fence_drv.initialized)
-                       continue;
-
-               /* wait for gpu to finish processing current batch */
-               r = amdgpu_fence_wait_empty(ring);
-               if (r) {
-                       /* delay GPU reset to resume */
-                       amdgpu_fence_driver_force_completion(ring);
-               }
-
-               /* disable the interrupt */
-               if (ring->fence_drv.irq_src)
-                       amdgpu_irq_put(adev, ring->fence_drv.irq_src,
-                                      ring->fence_drv.irq_type);
-       }
-}
-
-/**
- * amdgpu_fence_driver_resume - resume the fence driver
+ * amdgpu_fence_driver_hw_init - enable the fence driver
  * for all possible rings.
  *
  * @adev: amdgpu device pointer
  *
- * Resume the fence driver for all possible rings (all asics).
+ * Enable the fence driver for all possible rings (all asics).
  * Not all asics have all rings, so each asic will only
  * start the fence driver on the rings it has using
  * amdgpu_fence_driver_start_ring().
  * Returns 0 for success.
  */
-void amdgpu_fence_driver_resume(struct amdgpu_device *adev)
+void amdgpu_fence_driver_hw_init(struct amdgpu_device *adev)
 {
        int i;
 
index 39b6c6bfab453330d9734d797896de498fc52419..7709caeb233d678dcd376140537745d6ee381103 100644 (file)
 #include "smu_v11_0_i2c.h"
 #include "atom.h"
 #include "amdgpu_fru_eeprom.h"
+#include "amdgpu_eeprom.h"
 
-#define I2C_PRODUCT_INFO_ADDR          0xAC
-#define I2C_PRODUCT_INFO_ADDR_SIZE     0x2
-#define I2C_PRODUCT_INFO_OFFSET                0xC0
+#define FRU_EEPROM_MADDR        0x60000
+#define I2C_PRODUCT_INFO_OFFSET 0xC0
 
 static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
 {
@@ -62,19 +62,11 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
 }
 
 static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
-                          unsigned char *buff)
+                                 unsigned char *buff)
 {
        int ret, size;
-       struct i2c_msg msg = {
-                       .addr   = I2C_PRODUCT_INFO_ADDR,
-                       .flags  = I2C_M_RD,
-                       .buf    = buff,
-       };
-       buff[0] = 0;
-       buff[1] = addrptr;
-       msg.len = I2C_PRODUCT_INFO_ADDR_SIZE + 1;
-       ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1);
 
+       ret = amdgpu_eeprom_read(&adev->pm.smu_i2c, addrptr, buff, 1);
        if (ret < 1) {
                DRM_WARN("FRU: Failed to get size field");
                return ret;
@@ -83,13 +75,9 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
        /* The size returned by the i2c requires subtraction of 0xC0 since the
         * size apparently always reports as 0xC0+actual size.
         */
-       size = buff[2] - I2C_PRODUCT_INFO_OFFSET;
-       /* Add 1 since address field was 1 byte */
-       buff[1] = addrptr + 1;
-
-       msg.len = I2C_PRODUCT_INFO_ADDR_SIZE + size;
-       ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1);
+       size = buff[0] - I2C_PRODUCT_INFO_OFFSET;
 
+       ret = amdgpu_eeprom_read(&adev->pm.smu_i2c, addrptr + 1, buff, size);
        if (ret < 1) {
                DRM_WARN("FRU: Failed to get data field");
                return ret;
@@ -101,8 +89,8 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
 int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
 {
        unsigned char buff[34];
-       int addrptr, size;
-       int len;
+       u32 addrptr;
+       int size, len;
 
        if (!is_fru_eeprom_supported(adev))
                return 0;
@@ -125,7 +113,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
         * Bytes 8-a are all 1-byte and refer to the size of the entire struct,
         * and the language field, so just start from 0xb, manufacturer size
         */
-       addrptr = 0xb;
+       addrptr = FRU_EEPROM_MADDR + 0xb;
        size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
        if (size < 1) {
                DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size);
index 0d01cfaca77ef729c2c8b866f9a383d34a33cbbd..7dfdabe1cdf9d821b0269754326a3edf08666cc6 100644 (file)
@@ -584,7 +584,7 @@ void amdgpu_irq_gpu_reset_resume_helper(struct amdgpu_device *adev)
 {
        int i, j, k;
 
-       if (amdgpu_sriov_vf(adev))
+       if (amdgpu_sriov_vf(adev) || amdgpu_passthrough(adev))
                amdgpu_restore_msix(adev);
 
        for (i = 0; i < AMDGPU_IRQ_CLIENTID_MAX; ++i) {
index 96ef3f1051d86bcdf6a47579aa2b43ec2639c674..20b049ad61c10713586ea273f1f9d9c3f95de970 100644 (file)
@@ -374,8 +374,8 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
                fw_info->feature = adev->sdma.instance[query_fw->index].feature_version;
                break;
        case AMDGPU_INFO_FW_SOS:
-               fw_info->ver = adev->psp.sos_fw_version;
-               fw_info->feature = adev->psp.sos_feature_version;
+               fw_info->ver = adev->psp.sos.fw_version;
+               fw_info->feature = adev->psp.sos.feature_version;
                break;
        case AMDGPU_INFO_FW_ASD:
                fw_info->ver = adev->psp.asd_fw_version;
@@ -390,8 +390,8 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
                fw_info->feature = 0;
                break;
        case AMDGPU_INFO_FW_TOC:
-               fw_info->ver = adev->psp.toc_fw_version;
-               fw_info->feature = adev->psp.toc_feature_version;
+               fw_info->ver = adev->psp.toc.fw_version;
+               fw_info->feature = adev->psp.toc.feature_version;
                break;
        default:
                return -EINVAL;
@@ -1179,10 +1179,14 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
                pasid = 0;
        }
 
-       r = amdgpu_vm_init(adev, &fpriv->vm, pasid);
+       r = amdgpu_vm_init(adev, &fpriv->vm);
        if (r)
                goto error_pasid;
 
+       r = amdgpu_vm_set_pasid(adev, &fpriv->vm, pasid);
+       if (r)
+               goto error_vm;
+
        fpriv->prt_va = amdgpu_vm_bo_add(adev, &fpriv->vm, NULL);
        if (!fpriv->prt_va) {
                r = -ENOMEM;
@@ -1210,8 +1214,10 @@ error_vm:
        amdgpu_vm_fini(adev, &fpriv->vm);
 
 error_pasid:
-       if (pasid)
+       if (pasid) {
                amdgpu_pasid_free(pasid);
+               amdgpu_vm_set_pasid(adev, &fpriv->vm, 0);
+       }
 
        kfree(fpriv);
 
index 45295dce5c3ec10eeb12f2b831e5baf2303847c4..843052205bd5a719c77c31561bc6e5bb3d8a16cd 100644 (file)
@@ -95,6 +95,7 @@ struct amdgpu_nbio_funcs {
        void (*program_aspm)(struct amdgpu_device *adev);
        void (*apply_lc_spc_mode_wa)(struct amdgpu_device *adev);
        void (*apply_l1_link_width_reconfig_wa)(struct amdgpu_device *adev);
+       void (*clear_doorbell_interrupt)(struct amdgpu_device *adev);
 };
 
 struct amdgpu_nbio {
index 261283f5b4249719cfb0ec7c352dee1437f18d6f..d15eee98204d8fba5912cb56c5771ec915ee3694 100644 (file)
@@ -731,7 +731,7 @@ retry:
 /**
  * amdgpu_bo_add_to_shadow_list - add a BO to the shadow list
  *
- * @bo: BO that will be inserted into the shadow list
+ * @vmbo: BO that will be inserted into the shadow list
  *
  * Insert a BO to the shadow list.
  */
index 3ec5099ffeb6c716cb2c210186525910afeb1d4e..10b046147190730fc707dec23a4826c364cfae04 100644 (file)
@@ -24,7 +24,6 @@
  */
 
 #include <linux/firmware.h>
-#include <linux/dma-mapping.h>
 #include <drm/drm_drv.h>
 
 #include "amdgpu.h"
@@ -34,6 +33,7 @@
 #include "psp_v3_1.h"
 #include "psp_v10_0.h"
 #include "psp_v11_0.h"
+#include "psp_v11_0_8.h"
 #include "psp_v12_0.h"
 #include "psp_v13_0.h"
 
@@ -122,6 +122,12 @@ static int psp_early_init(void *handle)
                psp_v13_0_set_psp_funcs(psp);
                psp->autoload_supported = true;
                break;
+       case CHIP_CYAN_SKILLFISH:
+               if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) {
+                       psp_v11_0_8_set_psp_funcs(psp);
+                       psp->autoload_supported = false;
+               }
+               break;
        default:
                return -EINVAL;
        }
@@ -356,6 +362,44 @@ int psp_wait_for(struct psp_context *psp, uint32_t reg_index,
        return -ETIME;
 }
 
+static const char *psp_gfx_cmd_name(enum psp_gfx_cmd_id cmd_id)
+{
+       switch (cmd_id) {
+       case GFX_CMD_ID_LOAD_TA:
+               return "LOAD_TA";
+       case GFX_CMD_ID_UNLOAD_TA:
+               return "UNLOAD_TA";
+       case GFX_CMD_ID_INVOKE_CMD:
+               return "INVOKE_CMD";
+       case GFX_CMD_ID_LOAD_ASD:
+               return "LOAD_ASD";
+       case GFX_CMD_ID_SETUP_TMR:
+               return "SETUP_TMR";
+       case GFX_CMD_ID_LOAD_IP_FW:
+               return "LOAD_IP_FW";
+       case GFX_CMD_ID_DESTROY_TMR:
+               return "DESTROY_TMR";
+       case GFX_CMD_ID_SAVE_RESTORE:
+               return "SAVE_RESTORE_IP_FW";
+       case GFX_CMD_ID_SETUP_VMR:
+               return "SETUP_VMR";
+       case GFX_CMD_ID_DESTROY_VMR:
+               return "DESTROY_VMR";
+       case GFX_CMD_ID_PROG_REG:
+               return "PROG_REG";
+       case GFX_CMD_ID_GET_FW_ATTESTATION:
+               return "GET_FW_ATTESTATION";
+       case GFX_CMD_ID_LOAD_TOC:
+               return "ID_LOAD_TOC";
+       case GFX_CMD_ID_AUTOLOAD_RLC:
+               return "AUTOLOAD_RLC";
+       case GFX_CMD_ID_BOOT_CFG:
+               return "BOOT_CFG";
+       default:
+               return "UNKNOWN CMD";
+       }
+}
+
 static int
 psp_cmd_submit_buf(struct psp_context *psp,
                   struct amdgpu_firmware_info *ucode,
@@ -417,10 +461,10 @@ psp_cmd_submit_buf(struct psp_context *psp,
         */
        if (!skip_unsupport && (psp->cmd_buf_mem->resp.status || !timeout) && !ras_intr) {
                if (ucode)
-                       DRM_WARN("failed to load ucode id (%d) ",
-                                 ucode->ucode_id);
-               DRM_WARN("psp command (0x%X) failed and response status is (0x%X)\n",
-                        psp->cmd_buf_mem->cmd_id,
+                       DRM_WARN("failed to load ucode (%s) ",
+                                 amdgpu_ucode_name(ucode->ucode_id));
+               DRM_WARN("psp gfx command (%s) failed and response status is (0x%X)\n",
+                        psp_gfx_cmd_name(psp->cmd_buf_mem->cmd_id),
                         psp->cmd_buf_mem->resp.status);
                if (!timeout) {
                        ret = -EINVAL;
@@ -479,9 +523,9 @@ static int psp_load_toc(struct psp_context *psp,
        if (!cmd)
                return -ENOMEM;
        /* Copy toc to psp firmware private buffer */
-       psp_copy_fw(psp, psp->toc_start_addr, psp->toc_bin_size);
+       psp_copy_fw(psp, psp->toc.start_addr, psp->toc.size_bytes);
 
-       psp_prep_load_toc_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->toc_bin_size);
+       psp_prep_load_toc_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->toc.size_bytes);
 
        ret = psp_cmd_submit_buf(psp, NULL, cmd,
                                 psp->fence_buf_mc_addr);
@@ -511,8 +555,8 @@ static int psp_tmr_init(struct psp_context *psp)
        /* For ASICs support RLC autoload, psp will parse the toc
         * and calculate the total size of TMR needed */
        if (!amdgpu_sriov_vf(psp->adev) &&
-           psp->toc_start_addr &&
-           psp->toc_bin_size &&
+           psp->toc.start_addr &&
+           psp->toc.size_bytes &&
            psp->fw_pri_buf) {
                ret = psp_load_toc(psp, &tmr_size);
                if (ret) {
@@ -691,18 +735,18 @@ static int psp_rl_load(struct amdgpu_device *adev)
        struct psp_context *psp = &adev->psp;
        struct psp_gfx_cmd_resp *cmd = psp->cmd;
 
-       if (psp->rl_bin_size == 0)
+       if (!is_psp_fw_valid(psp->rl))
                return 0;
 
        memset(psp->fw_pri_buf, 0, PSP_1_MEG);
-       memcpy(psp->fw_pri_buf, psp->rl_start_addr, psp->rl_bin_size);
+       memcpy(psp->fw_pri_buf, psp->rl.start_addr, psp->rl.size_bytes);
 
        memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
 
        cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW;
        cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(psp->fw_pri_mc_addr);
        cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(psp->fw_pri_mc_addr);
-       cmd->cmd.cmd_load_ip_fw.fw_size = psp->rl_bin_size;
+       cmd->cmd.cmd_load_ip_fw.fw_size = psp->rl.size_bytes;
        cmd->cmd.cmd_load_ip_fw.fw_type = GFX_FW_TYPE_REG_LIST;
 
        return psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
@@ -1041,6 +1085,12 @@ int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id)
        return 0;
 }
 
+static bool psp_xgmi_peer_link_info_supported(struct psp_context *psp)
+{
+       return psp->adev->asic_type == CHIP_ALDEBARAN &&
+                               psp->ta_xgmi_ucode_version >= 0x2000000b;
+}
+
 int psp_xgmi_get_topology_info(struct psp_context *psp,
                               int number_devices,
                               struct psp_xgmi_topology_info *topology)
@@ -1084,6 +1134,23 @@ int psp_xgmi_get_topology_info(struct psp_context *psp,
                topology->nodes[i].sdma_engine = topology_info_output->nodes[i].sdma_engine;
        }
 
+       /* Invoke xgmi ta again to get the link information */
+       if (psp_xgmi_peer_link_info_supported(psp)) {
+               struct ta_xgmi_cmd_get_peer_link_info_output *link_info_output;
+
+               xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_PEER_LINKS;
+
+               ret = psp_xgmi_invoke(psp, TA_COMMAND_XGMI__GET_PEER_LINKS);
+
+               if (ret)
+                       return ret;
+
+               link_info_output = &xgmi_cmd->xgmi_out_message.get_link_info;
+               for (i = 0; i < topology->num_nodes; i++)
+                       topology->nodes[i].num_links =
+                                       link_info_output->nodes[i].num_links;
+       }
+
        return 0;
 }
 
@@ -2069,7 +2136,7 @@ static int psp_hw_start(struct psp_context *psp)
        int ret;
 
        if (!amdgpu_sriov_vf(adev)) {
-               if (psp->kdb_bin_size &&
+               if ((is_psp_fw_valid(psp->kdb)) &&
                    (psp->funcs->bootloader_load_kdb != NULL)) {
                        ret = psp_bootloader_load_kdb(psp);
                        if (ret) {
@@ -2078,7 +2145,8 @@ static int psp_hw_start(struct psp_context *psp)
                        }
                }
 
-               if (psp->spl_bin_size) {
+               if ((is_psp_fw_valid(psp->spl)) &&
+                   (psp->funcs->bootloader_load_spl != NULL)) {
                        ret = psp_bootloader_load_spl(psp);
                        if (ret) {
                                DRM_ERROR("PSP load spl failed!\n");
@@ -2086,16 +2154,49 @@ static int psp_hw_start(struct psp_context *psp)
                        }
                }
 
-               ret = psp_bootloader_load_sysdrv(psp);
-               if (ret) {
-                       DRM_ERROR("PSP load sysdrv failed!\n");
-                       return ret;
+               if ((is_psp_fw_valid(psp->sys)) &&
+                   (psp->funcs->bootloader_load_sysdrv != NULL)) {
+                       ret = psp_bootloader_load_sysdrv(psp);
+                       if (ret) {
+                               DRM_ERROR("PSP load sys drv failed!\n");
+                               return ret;
+                       }
                }
 
-               ret = psp_bootloader_load_sos(psp);
-               if (ret) {
-                       DRM_ERROR("PSP load sos failed!\n");
-                       return ret;
+               if ((is_psp_fw_valid(psp->soc_drv)) &&
+                   (psp->funcs->bootloader_load_soc_drv != NULL)) {
+                       ret = psp_bootloader_load_soc_drv(psp);
+                       if (ret) {
+                               DRM_ERROR("PSP load soc drv failed!\n");
+                               return ret;
+                       }
+               }
+
+               if ((is_psp_fw_valid(psp->intf_drv)) &&
+                   (psp->funcs->bootloader_load_intf_drv != NULL)) {
+                       ret = psp_bootloader_load_intf_drv(psp);
+                       if (ret) {
+                               DRM_ERROR("PSP load intf drv failed!\n");
+                               return ret;
+                       }
+               }
+
+               if ((is_psp_fw_valid(psp->dbg_drv)) &&
+                   (psp->funcs->bootloader_load_dbg_drv != NULL)) {
+                       ret = psp_bootloader_load_dbg_drv(psp);
+                       if (ret) {
+                               DRM_ERROR("PSP load dbg drv failed!\n");
+                               return ret;
+                       }
+               }
+
+               if ((is_psp_fw_valid(psp->sos)) &&
+                   (psp->funcs->bootloader_load_sos != NULL)) {
+                       ret = psp_bootloader_load_sos(psp);
+                       if (ret) {
+                               DRM_ERROR("PSP load sos failed!\n");
+                               return ret;
+                       }
                }
        }
 
@@ -2313,7 +2414,7 @@ static int psp_prep_load_ip_fw_cmd_buf(struct amdgpu_firmware_info *ucode,
        return ret;
 }
 
-static int psp_execute_np_fw_load(struct psp_context *psp,
+static int psp_execute_non_psp_fw_load(struct psp_context *psp,
                                  struct amdgpu_firmware_info *ucode)
 {
        int ret = 0;
@@ -2349,7 +2450,7 @@ static int psp_load_smu_fw(struct psp_context *psp)
                }
        }
 
-       ret = psp_execute_np_fw_load(psp, ucode);
+       ret = psp_execute_non_psp_fw_load(psp, ucode);
 
        if (ret)
                DRM_ERROR("PSP load smu failed!\n");
@@ -2404,14 +2505,14 @@ int psp_load_fw_list(struct psp_context *psp,
        for (i = 0; i < ucode_count; ++i) {
                ucode = ucode_list[i];
                psp_print_fw_hdr(psp, ucode);
-               ret = psp_execute_np_fw_load(psp, ucode);
+               ret = psp_execute_non_psp_fw_load(psp, ucode);
                if (ret)
                        return ret;
        }
        return ret;
 }
 
-static int psp_np_fw_load(struct psp_context *psp)
+static int psp_load_non_psp_fw(struct psp_context *psp)
 {
        int i, ret;
        struct amdgpu_firmware_info *ucode;
@@ -2450,7 +2551,7 @@ static int psp_np_fw_load(struct psp_context *psp)
 
                psp_print_fw_hdr(psp, ucode);
 
-               ret = psp_execute_np_fw_load(psp, ucode);
+               ret = psp_execute_non_psp_fw_load(psp, ucode);
                if (ret)
                        return ret;
 
@@ -2527,7 +2628,7 @@ skip_memalloc:
        if (ret)
                goto failed;
 
-       ret = psp_np_fw_load(psp);
+       ret = psp_load_non_psp_fw(psp);
        if (ret)
                goto failed;
 
@@ -2727,7 +2828,7 @@ static int psp_resume(void *handle)
        if (ret)
                goto failed;
 
-       ret = psp_np_fw_load(psp);
+       ret = psp_load_non_psp_fw(psp);
        if (ret)
                goto failed;
 
@@ -2825,7 +2926,7 @@ int psp_update_vcn_sram(struct amdgpu_device *adev, int inst_idx,
        ucode.mc_addr = cmd_gpu_addr;
        ucode.ucode_size = cmd_size;
 
-       return psp_execute_np_fw_load(&adev->psp, &ucode);
+       return psp_execute_non_psp_fw_load(&adev->psp, &ucode);
 }
 
 int psp_ring_cmd_submit(struct psp_context *psp,
@@ -2918,7 +3019,7 @@ int psp_init_toc_microcode(struct psp_context *psp,
                           const char *chip_name)
 {
        struct amdgpu_device *adev = psp->adev;
-       char fw_name[30];
+       char fw_name[PSP_FW_NAME_LEN];
        const struct psp_firmware_header_v1_0 *toc_hdr;
        int err = 0;
 
@@ -2937,10 +3038,10 @@ int psp_init_toc_microcode(struct psp_context *psp,
                goto out;
 
        toc_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.toc_fw->data;
-       adev->psp.toc_fw_version = le32_to_cpu(toc_hdr->header.ucode_version);
-       adev->psp.toc_feature_version = le32_to_cpu(toc_hdr->sos.fw_version);
-       adev->psp.toc_bin_size = le32_to_cpu(toc_hdr->header.ucode_size_bytes);
-       adev->psp.toc_start_addr = (uint8_t *)toc_hdr +
+       adev->psp.toc.fw_version = le32_to_cpu(toc_hdr->header.ucode_version);
+       adev->psp.toc.feature_version = le32_to_cpu(toc_hdr->sos.fw_version);
+       adev->psp.toc.size_bytes = le32_to_cpu(toc_hdr->header.ucode_size_bytes);
+       adev->psp.toc.start_addr = (uint8_t *)toc_hdr +
                                le32_to_cpu(toc_hdr->header.ucode_array_offset_bytes);
        return 0;
 out:
@@ -2950,6 +3051,82 @@ out:
        return err;
 }
 
+static int parse_sos_bin_descriptor(struct psp_context *psp,
+                                  const struct psp_fw_bin_desc *desc,
+                                  const struct psp_firmware_header_v2_0 *sos_hdr)
+{
+       uint8_t *ucode_start_addr  = NULL;
+
+       if (!psp || !desc || !sos_hdr)
+               return -EINVAL;
+
+       ucode_start_addr  = (uint8_t *)sos_hdr +
+                           le32_to_cpu(desc->offset_bytes) +
+                           le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes);
+
+       switch (desc->fw_type) {
+       case PSP_FW_TYPE_PSP_SOS:
+               psp->sos.fw_version        = le32_to_cpu(desc->fw_version);
+               psp->sos.feature_version   = le32_to_cpu(desc->fw_version);
+               psp->sos.size_bytes        = le32_to_cpu(desc->size_bytes);
+               psp->sos.start_addr        = ucode_start_addr;
+               break;
+       case PSP_FW_TYPE_PSP_SYS_DRV:
+               psp->sys.fw_version        = le32_to_cpu(desc->fw_version);
+               psp->sys.feature_version   = le32_to_cpu(desc->fw_version);
+               psp->sys.size_bytes        = le32_to_cpu(desc->size_bytes);
+               psp->sys.start_addr        = ucode_start_addr;
+               break;
+       case PSP_FW_TYPE_PSP_KDB:
+               psp->kdb.fw_version        = le32_to_cpu(desc->fw_version);
+               psp->kdb.feature_version   = le32_to_cpu(desc->fw_version);
+               psp->kdb.size_bytes        = le32_to_cpu(desc->size_bytes);
+               psp->kdb.start_addr        = ucode_start_addr;
+               break;
+       case PSP_FW_TYPE_PSP_TOC:
+               psp->toc.fw_version        = le32_to_cpu(desc->fw_version);
+               psp->toc.feature_version   = le32_to_cpu(desc->fw_version);
+               psp->toc.size_bytes        = le32_to_cpu(desc->size_bytes);
+               psp->toc.start_addr        = ucode_start_addr;
+               break;
+       case PSP_FW_TYPE_PSP_SPL:
+               psp->spl.fw_version        = le32_to_cpu(desc->fw_version);
+               psp->spl.feature_version   = le32_to_cpu(desc->fw_version);
+               psp->spl.size_bytes        = le32_to_cpu(desc->size_bytes);
+               psp->spl.start_addr        = ucode_start_addr;
+               break;
+       case PSP_FW_TYPE_PSP_RL:
+               psp->rl.fw_version         = le32_to_cpu(desc->fw_version);
+               psp->rl.feature_version    = le32_to_cpu(desc->fw_version);
+               psp->rl.size_bytes         = le32_to_cpu(desc->size_bytes);
+               psp->rl.start_addr         = ucode_start_addr;
+               break;
+       case PSP_FW_TYPE_PSP_SOC_DRV:
+               psp->soc_drv.fw_version         = le32_to_cpu(desc->fw_version);
+               psp->soc_drv.feature_version    = le32_to_cpu(desc->fw_version);
+               psp->soc_drv.size_bytes         = le32_to_cpu(desc->size_bytes);
+               psp->soc_drv.start_addr         = ucode_start_addr;
+               break;
+       case PSP_FW_TYPE_PSP_INTF_DRV:
+               psp->intf_drv.fw_version        = le32_to_cpu(desc->fw_version);
+               psp->intf_drv.feature_version   = le32_to_cpu(desc->fw_version);
+               psp->intf_drv.size_bytes        = le32_to_cpu(desc->size_bytes);
+               psp->intf_drv.start_addr        = ucode_start_addr;
+               break;
+       case PSP_FW_TYPE_PSP_DBG_DRV:
+               psp->dbg_drv.fw_version         = le32_to_cpu(desc->fw_version);
+               psp->dbg_drv.feature_version    = le32_to_cpu(desc->fw_version);
+               psp->dbg_drv.size_bytes         = le32_to_cpu(desc->size_bytes);
+               psp->dbg_drv.start_addr         = ucode_start_addr;
+               break;
+       default:
+               dev_warn(psp->adev->dev, "Unsupported PSP FW type: %d\n", desc->fw_type);
+               break;
+       }
+
+       return 0;
+}
+
 static int psp_init_sos_base_fw(struct amdgpu_device *adev)
 {
        const struct psp_firmware_header_v1_0 *sos_hdr;
@@ -2961,32 +3138,32 @@ static int psp_init_sos_base_fw(struct amdgpu_device *adev)
                le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes);
 
        if (adev->gmc.xgmi.connected_to_cpu || (adev->asic_type != CHIP_ALDEBARAN)) {
-               adev->psp.sos_fw_version = le32_to_cpu(sos_hdr->header.ucode_version);
-               adev->psp.sos_feature_version = le32_to_cpu(sos_hdr->sos.fw_version);
+               adev->psp.sos.fw_version = le32_to_cpu(sos_hdr->header.ucode_version);
+               adev->psp.sos.feature_version = le32_to_cpu(sos_hdr->sos.fw_version);
 
-               adev->psp.sys_bin_size = le32_to_cpu(sos_hdr->sos.offset_bytes);
-               adev->psp.sys_start_addr = ucode_array_start_addr;
+               adev->psp.sys.size_bytes = le32_to_cpu(sos_hdr->sos.offset_bytes);
+               adev->psp.sys.start_addr = ucode_array_start_addr;
 
-               adev->psp.sos_bin_size = le32_to_cpu(sos_hdr->sos.size_bytes);
-               adev->psp.sos_start_addr = ucode_array_start_addr +
+               adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr->sos.size_bytes);
+               adev->psp.sos.start_addr = ucode_array_start_addr +
                                le32_to_cpu(sos_hdr->sos.offset_bytes);
        } else {
                /* Load alternate PSP SOS FW */
                sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data;
 
-               adev->psp.sos_fw_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version);
-               adev->psp.sos_feature_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version);
+               adev->psp.sos.fw_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version);
+               adev->psp.sos.feature_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version);
 
-               adev->psp.sys_bin_size = le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.size_bytes);
-               adev->psp.sys_start_addr = ucode_array_start_addr +
+               adev->psp.sys.size_bytes = le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.size_bytes);
+               adev->psp.sys.start_addr = ucode_array_start_addr +
                        le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.offset_bytes);
 
-               adev->psp.sos_bin_size = le32_to_cpu(sos_hdr_v1_3->sos_aux.size_bytes);
-               adev->psp.sos_start_addr = ucode_array_start_addr +
+               adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr_v1_3->sos_aux.size_bytes);
+               adev->psp.sos.start_addr = ucode_array_start_addr +
                        le32_to_cpu(sos_hdr_v1_3->sos_aux.offset_bytes);
        }
 
-       if ((adev->psp.sys_bin_size == 0) || (adev->psp.sos_bin_size == 0)) {
+       if ((adev->psp.sys.size_bytes == 0) || (adev->psp.sos.size_bytes == 0)) {
                dev_warn(adev->dev, "PSP SOS FW not available");
                return -EINVAL;
        }
@@ -3003,8 +3180,10 @@ int psp_init_sos_microcode(struct psp_context *psp,
        const struct psp_firmware_header_v1_1 *sos_hdr_v1_1;
        const struct psp_firmware_header_v1_2 *sos_hdr_v1_2;
        const struct psp_firmware_header_v1_3 *sos_hdr_v1_3;
+       const struct psp_firmware_header_v2_0 *sos_hdr_v2_0;
        int err = 0;
        uint8_t *ucode_array_start_addr;
+       int fw_index = 0;
 
        if (!chip_name) {
                dev_err(adev->dev, "invalid chip name for sos microcode\n");
@@ -3033,35 +3212,52 @@ int psp_init_sos_microcode(struct psp_context *psp,
 
                if (sos_hdr->header.header_version_minor == 1) {
                        sos_hdr_v1_1 = (const struct psp_firmware_header_v1_1 *)adev->psp.sos_fw->data;
-                       adev->psp.toc_bin_size = le32_to_cpu(sos_hdr_v1_1->toc.size_bytes);
-                       adev->psp.toc_start_addr = (uint8_t *)adev->psp.sys_start_addr +
+                       adev->psp.toc.size_bytes = le32_to_cpu(sos_hdr_v1_1->toc.size_bytes);
+                       adev->psp.toc.start_addr = (uint8_t *)adev->psp.sys.start_addr +
                                        le32_to_cpu(sos_hdr_v1_1->toc.offset_bytes);
-                       adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_1->kdb.size_bytes);
-                       adev->psp.kdb_start_addr = (uint8_t *)adev->psp.sys_start_addr +
+                       adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_1->kdb.size_bytes);
+                       adev->psp.kdb.start_addr = (uint8_t *)adev->psp.sys.start_addr +
                                        le32_to_cpu(sos_hdr_v1_1->kdb.offset_bytes);
                }
                if (sos_hdr->header.header_version_minor == 2) {
                        sos_hdr_v1_2 = (const struct psp_firmware_header_v1_2 *)adev->psp.sos_fw->data;
-                       adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_2->kdb.size_bytes);
-                       adev->psp.kdb_start_addr = (uint8_t *)adev->psp.sys_start_addr +
+                       adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_2->kdb.size_bytes);
+                       adev->psp.kdb.start_addr = (uint8_t *)adev->psp.sys.start_addr +
                                                    le32_to_cpu(sos_hdr_v1_2->kdb.offset_bytes);
                }
                if (sos_hdr->header.header_version_minor == 3) {
                        sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data;
-                       adev->psp.toc_bin_size = le32_to_cpu(sos_hdr_v1_3->v1_1.toc.size_bytes);
-                       adev->psp.toc_start_addr = ucode_array_start_addr +
+                       adev->psp.toc.size_bytes = le32_to_cpu(sos_hdr_v1_3->v1_1.toc.size_bytes);
+                       adev->psp.toc.start_addr = ucode_array_start_addr +
                                le32_to_cpu(sos_hdr_v1_3->v1_1.toc.offset_bytes);
-                       adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.size_bytes);
-                       adev->psp.kdb_start_addr = ucode_array_start_addr +
+                       adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.size_bytes);
+                       adev->psp.kdb.start_addr = ucode_array_start_addr +
                                le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.offset_bytes);
-                       adev->psp.spl_bin_size = le32_to_cpu(sos_hdr_v1_3->spl.size_bytes);
-                       adev->psp.spl_start_addr = ucode_array_start_addr +
+                       adev->psp.spl.size_bytes = le32_to_cpu(sos_hdr_v1_3->spl.size_bytes);
+                       adev->psp.spl.start_addr = ucode_array_start_addr +
                                le32_to_cpu(sos_hdr_v1_3->spl.offset_bytes);
-                       adev->psp.rl_bin_size = le32_to_cpu(sos_hdr_v1_3->rl.size_bytes);
-                       adev->psp.rl_start_addr = ucode_array_start_addr +
+                       adev->psp.rl.size_bytes = le32_to_cpu(sos_hdr_v1_3->rl.size_bytes);
+                       adev->psp.rl.start_addr = ucode_array_start_addr +
                                le32_to_cpu(sos_hdr_v1_3->rl.offset_bytes);
                }
                break;
+       case 2:
+               sos_hdr_v2_0 = (const struct psp_firmware_header_v2_0 *)adev->psp.sos_fw->data;
+
+               if (le32_to_cpu(sos_hdr_v2_0->psp_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) {
+                       dev_err(adev->dev, "packed SOS count exceeds maximum limit\n");
+                       err = -EINVAL;
+                       goto out;
+               }
+
+               for (fw_index = 0; fw_index < le32_to_cpu(sos_hdr_v2_0->psp_fw_bin_count); fw_index++) {
+                       err = parse_sos_bin_descriptor(psp,
+                                                      &sos_hdr_v2_0->psp_fw_bin[fw_index],
+                                                      sos_hdr_v2_0);
+                       if (err)
+                               goto out;
+               }
+               break;
        default:
                dev_err(adev->dev,
                        "unsupported psp sos firmware\n");
@@ -3080,7 +3276,7 @@ out:
 }
 
 static int parse_ta_bin_descriptor(struct psp_context *psp,
-                                  const struct ta_fw_bin_desc *desc,
+                                  const struct psp_fw_bin_desc *desc,
                                   const struct ta_firmware_header_v2_0 *ta_hdr)
 {
        uint8_t *ucode_start_addr  = NULL;
@@ -3168,7 +3364,7 @@ int psp_init_ta_microcode(struct psp_context *psp,
                goto out;
        }
 
-       if (le32_to_cpu(ta_hdr->ta_fw_bin_count) >= UCODE_MAX_TA_PACKAGING) {
+       if (le32_to_cpu(ta_hdr->ta_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) {
                dev_err(adev->dev, "packed TA count exceeds maximum limit\n");
                err = -EINVAL;
                goto out;
@@ -3235,11 +3431,12 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
 {
        struct drm_device *ddev = dev_get_drvdata(dev);
        struct amdgpu_device *adev = drm_to_adev(ddev);
-       void *cpu_addr;
-       dma_addr_t dma_addr;
        int ret, idx;
        char fw_name[100];
        const struct firmware *usbc_pd_fw;
+       struct amdgpu_bo *fw_buf_bo = NULL;
+       uint64_t fw_pri_mc_addr;
+       void *fw_pri_cpu_addr;
 
        if (!adev->ip_blocks[AMD_IP_BLOCK_TYPE_PSP].status.late_initialized) {
                DRM_INFO("PSP block is not ready yet.");
@@ -3254,31 +3451,24 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
        if (ret)
                goto fail;
 
-       /* We need contiguous physical mem to place the FW  for psp to access */
-       cpu_addr = dma_alloc_coherent(adev->dev, usbc_pd_fw->size, &dma_addr, GFP_KERNEL);
-
-       ret = dma_mapping_error(adev->dev, dma_addr);
+       /* LFB address which is aligned to 1MB boundary per PSP request */
+       ret = amdgpu_bo_create_kernel(adev, usbc_pd_fw->size, 0x100000,
+                                               AMDGPU_GEM_DOMAIN_VRAM,
+                                               &fw_buf_bo,
+                                               &fw_pri_mc_addr,
+                                               &fw_pri_cpu_addr);
        if (ret)
                goto rel_buf;
 
-       memcpy_toio(cpu_addr, usbc_pd_fw->data, usbc_pd_fw->size);
-
-       /*
-        * x86 specific workaround.
-        * Without it the buffer is invisible in PSP.
-        *
-        * TODO Remove once PSP starts snooping CPU cache
-        */
-#ifdef CONFIG_X86
-       clflush_cache_range(cpu_addr, (usbc_pd_fw->size & ~(L1_CACHE_BYTES - 1)));
-#endif
+       memcpy_toio(fw_pri_cpu_addr, usbc_pd_fw->data, usbc_pd_fw->size);
 
        mutex_lock(&adev->psp.mutex);
-       ret = psp_load_usbc_pd_fw(&adev->psp, dma_addr);
+       ret = psp_load_usbc_pd_fw(&adev->psp, fw_pri_mc_addr);
        mutex_unlock(&adev->psp.mutex);
 
+       amdgpu_bo_free_kernel(&fw_buf_bo, &fw_pri_mc_addr, &fw_pri_cpu_addr);
+
 rel_buf:
-       dma_free_coherent(adev->dev, usbc_pd_fw->size, cpu_addr, dma_addr);
        release_firmware(usbc_pd_fw);
 fail:
        if (ret) {
@@ -3307,7 +3497,10 @@ static DEVICE_ATTR(usbc_pd_fw, S_IRUGO | S_IWUSR,
                   psp_usbc_pd_fw_sysfs_read,
                   psp_usbc_pd_fw_sysfs_write);
 
-
+int is_psp_fw_valid(struct psp_bin_desc bin)
+{
+       return bin.size_bytes;
+}
 
 const struct amd_ip_funcs psp_ip_funcs = {
        .name = "psp",
@@ -3369,6 +3562,14 @@ const struct amdgpu_ip_block_version psp_v11_0_ip_block =
        .funcs = &psp_ip_funcs,
 };
 
+const struct amdgpu_ip_block_version psp_v11_0_8_ip_block = {
+       .type = AMD_IP_BLOCK_TYPE_PSP,
+       .major = 11,
+       .minor = 0,
+       .rev = 8,
+       .funcs = &psp_ip_funcs,
+};
+
 const struct amdgpu_ip_block_version psp_v12_0_ip_block =
 {
        .type = AMD_IP_BLOCK_TYPE_PSP,
index 3030ec24eb3b708eab0c76d6c504e003cd26df19..4435b180ace0bcd5b4354c7c58d5e34bb8596c40 100644 (file)
 struct psp_context;
 struct psp_xgmi_node_info;
 struct psp_xgmi_topology_info;
+struct psp_bin_desc;
 
 enum psp_bootloader_cmd {
        PSP_BL__LOAD_SYSDRV             = 0x10000,
        PSP_BL__LOAD_SOSDRV             = 0x20000,
        PSP_BL__LOAD_KEY_DATABASE       = 0x80000,
+       PSP_BL__LOAD_SOCDRV             = 0x90000,
+       PSP_BL__LOAD_INTFDRV            = 0xA0000,
+       PSP_BL__LOAD_DBGDRV             = 0xB0000,
        PSP_BL__DRAM_LONG_TRAIN         = 0x100000,
        PSP_BL__DRAM_SHORT_TRAIN        = 0x200000,
        PSP_BL__LOAD_TOS_SPL_TABLE      = 0x10000000,
@@ -93,6 +97,9 @@ struct psp_funcs
        int (*bootloader_load_kdb)(struct psp_context *psp);
        int (*bootloader_load_spl)(struct psp_context *psp);
        int (*bootloader_load_sysdrv)(struct psp_context *psp);
+       int (*bootloader_load_soc_drv)(struct psp_context *psp);
+       int (*bootloader_load_intf_drv)(struct psp_context *psp);
+       int (*bootloader_load_dbg_drv)(struct psp_context *psp);
        int (*bootloader_load_sos)(struct psp_context *psp);
        int (*ring_init)(struct psp_context *psp, enum psp_ring_type ring_type);
        int (*ring_create)(struct psp_context *psp,
@@ -106,7 +113,7 @@ struct psp_funcs
        int (*mem_training)(struct psp_context *psp, uint32_t ops);
        uint32_t (*ring_get_wptr)(struct psp_context *psp);
        void (*ring_set_wptr)(struct psp_context *psp, uint32_t value);
-       int (*load_usbc_pd_fw)(struct psp_context *psp, dma_addr_t dma_addr);
+       int (*load_usbc_pd_fw)(struct psp_context *psp, uint64_t fw_pri_mc_addr);
        int (*read_usbc_pd_fw)(struct psp_context *psp, uint32_t *fw_ver);
 };
 
@@ -116,6 +123,7 @@ struct psp_xgmi_node_info {
        uint8_t                                 num_hops;
        uint8_t                                 is_sharing_enabled;
        enum ta_xgmi_assigned_sdma_engine       sdma_engine;
+       uint8_t                                 num_links;
 };
 
 struct psp_xgmi_topology_info {
@@ -282,6 +290,13 @@ struct psp_runtime_boot_cfg_entry {
        uint32_t reserved;
 };
 
+struct psp_bin_desc {
+       uint32_t fw_version;
+       uint32_t feature_version;
+       uint32_t size_bytes;
+       uint8_t *start_addr;
+};
+
 struct psp_context
 {
        struct amdgpu_device            *adev;
@@ -297,20 +312,15 @@ struct psp_context
 
        /* sos firmware */
        const struct firmware           *sos_fw;
-       uint32_t                        sos_fw_version;
-       uint32_t                        sos_feature_version;
-       uint32_t                        sys_bin_size;
-       uint32_t                        sos_bin_size;
-       uint32_t                        toc_bin_size;
-       uint32_t                        kdb_bin_size;
-       uint32_t                        spl_bin_size;
-       uint32_t                        rl_bin_size;
-       uint8_t                         *sys_start_addr;
-       uint8_t                         *sos_start_addr;
-       uint8_t                         *toc_start_addr;
-       uint8_t                         *kdb_start_addr;
-       uint8_t                         *spl_start_addr;
-       uint8_t                         *rl_start_addr;
+       struct psp_bin_desc             sys;
+       struct psp_bin_desc             sos;
+       struct psp_bin_desc             toc;
+       struct psp_bin_desc             kdb;
+       struct psp_bin_desc             spl;
+       struct psp_bin_desc             rl;
+       struct psp_bin_desc             soc_drv;
+       struct psp_bin_desc             intf_drv;
+       struct psp_bin_desc             dbg_drv;
 
        /* tmr buffer */
        struct amdgpu_bo                *tmr_bo;
@@ -325,8 +335,6 @@ struct psp_context
 
        /* toc firmware */
        const struct firmware           *toc_fw;
-       uint32_t                        toc_fw_version;
-       uint32_t                        toc_feature_version;
 
        /* fence buffer */
        struct amdgpu_bo                *fence_buf_bo;
@@ -402,6 +410,12 @@ struct amdgpu_psp_funcs {
                ((psp)->funcs->bootloader_load_spl ? (psp)->funcs->bootloader_load_spl((psp)) : 0)
 #define psp_bootloader_load_sysdrv(psp) \
                ((psp)->funcs->bootloader_load_sysdrv ? (psp)->funcs->bootloader_load_sysdrv((psp)) : 0)
+#define psp_bootloader_load_soc_drv(psp) \
+               ((psp)->funcs->bootloader_load_soc_drv ? (psp)->funcs->bootloader_load_soc_drv((psp)) : 0)
+#define psp_bootloader_load_intf_drv(psp) \
+               ((psp)->funcs->bootloader_load_intf_drv ? (psp)->funcs->bootloader_load_intf_drv((psp)) : 0)
+#define psp_bootloader_load_dbg_drv(psp) \
+               ((psp)->funcs->bootloader_load_dbg_drv ? (psp)->funcs->bootloader_load_dbg_drv((psp)) : 0)
 #define psp_bootloader_load_sos(psp) \
                ((psp)->funcs->bootloader_load_sos ? (psp)->funcs->bootloader_load_sos((psp)) : 0)
 #define psp_smu_reload_quirk(psp) \
@@ -414,9 +428,9 @@ struct amdgpu_psp_funcs {
 #define psp_ring_get_wptr(psp) (psp)->funcs->ring_get_wptr((psp))
 #define psp_ring_set_wptr(psp, value) (psp)->funcs->ring_set_wptr((psp), (value))
 
-#define psp_load_usbc_pd_fw(psp, dma_addr) \
+#define psp_load_usbc_pd_fw(psp, fw_pri_mc_addr) \
        ((psp)->funcs->load_usbc_pd_fw ? \
-       (psp)->funcs->load_usbc_pd_fw((psp), (dma_addr)) : -EINVAL)
+       (psp)->funcs->load_usbc_pd_fw((psp), (fw_pri_mc_addr)) : -EINVAL)
 
 #define psp_read_usbc_pd_fw(psp, fw_ver) \
        ((psp)->funcs->read_usbc_pd_fw ? \
@@ -427,6 +441,7 @@ extern const struct amd_ip_funcs psp_ip_funcs;
 extern const struct amdgpu_ip_block_version psp_v3_1_ip_block;
 extern const struct amdgpu_ip_block_version psp_v10_0_ip_block;
 extern const struct amdgpu_ip_block_version psp_v11_0_ip_block;
+extern const struct amdgpu_ip_block_version psp_v11_0_8_ip_block;
 extern const struct amdgpu_ip_block_version psp_v12_0_ip_block;
 extern const struct amdgpu_ip_block_version psp_v13_0_ip_block;
 
@@ -483,4 +498,5 @@ int psp_load_fw_list(struct psp_context *psp,
                     struct amdgpu_firmware_info **ucode_list, int ucode_count);
 void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size);
 
+int is_psp_fw_valid(struct psp_bin_desc bin);
 #endif
index fc66aca285944649b4906bcc83fd3301a4d5d5b2..194f7ccfbf946c4a94eb88196f02b60ffb3e36e9 100644 (file)
@@ -71,8 +71,8 @@ const char *ras_block_string[] = {
 /* inject address is 52 bits */
 #define        RAS_UMC_INJECT_ADDR_LIMIT       (0x1ULL << 52)
 
-/* typical ECC bad page rate(1 bad page per 100MB VRAM) */
-#define RAS_BAD_PAGE_RATE              (100 * 1024 * 1024ULL)
+/* typical ECC bad page rate is 1 bad page per 100MB VRAM */
+#define RAS_BAD_PAGE_COVER              (100 * 1024 * 1024ULL)
 
 enum amdgpu_ras_retire_page_reservation {
        AMDGPU_RAS_RETIRE_PAGE_RESERVED,
@@ -355,8 +355,9 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f,
  *     to see which blocks support RAS on a particular asic.
  *
  */
-static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *buf,
-               size_t size, loff_t *pos)
+static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f,
+                                            const char __user *buf,
+                                            size_t size, loff_t *pos)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
        struct ras_debug_if data;
@@ -370,7 +371,7 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *
 
        ret = amdgpu_ras_debugfs_ctrl_parse_data(f, buf, size, pos, &data);
        if (ret)
-               return -EINVAL;
+               return ret;
 
        if (data.op == 3) {
                ret = amdgpu_reserve_page_direct(adev, data.inject.address);
@@ -403,9 +404,9 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *
                /* umc ce/ue error injection for a bad page is not allowed */
                if ((data.head.block == AMDGPU_RAS_BLOCK__UMC) &&
                    amdgpu_ras_check_bad_page(adev, data.inject.address)) {
-                       dev_warn(adev->dev, "RAS WARN: 0x%llx has been marked "
-                                       "as bad before error injection!\n",
-                                       data.inject.address);
+                       dev_warn(adev->dev, "RAS WARN: inject: 0x%llx has "
+                                "already been marked as bad!\n",
+                                data.inject.address);
                        break;
                }
 
@@ -439,21 +440,24 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *
  * will reset EEPROM table to 0 entries.
  *
  */
-static ssize_t amdgpu_ras_debugfs_eeprom_write(struct file *f, const char __user *buf,
-               size_t size, loff_t *pos)
+static ssize_t amdgpu_ras_debugfs_eeprom_write(struct file *f,
+                                              const char __user *buf,
+                                              size_t size, loff_t *pos)
 {
        struct amdgpu_device *adev =
                (struct amdgpu_device *)file_inode(f)->i_private;
        int ret;
 
        ret = amdgpu_ras_eeprom_reset_table(
-                       &(amdgpu_ras_get_context(adev)->eeprom_control));
+               &(amdgpu_ras_get_context(adev)->eeprom_control));
 
-       if (ret == 1) {
+       if (!ret) {
+               /* Something was written to EEPROM.
+                */
                amdgpu_ras_get_context(adev)->flags = RAS_DEFAULT_FLAGS;
                return size;
        } else {
-               return -EIO;
+               return ret;
        }
 }
 
@@ -1316,6 +1320,12 @@ static struct dentry *amdgpu_ras_debugfs_create_ctrl_node(struct amdgpu_device *
                           &con->bad_page_cnt_threshold);
        debugfs_create_x32("ras_hw_enabled", 0444, dir, &adev->ras_hw_enabled);
        debugfs_create_x32("ras_enabled", 0444, dir, &adev->ras_enabled);
+       debugfs_create_file("ras_eeprom_size", S_IRUGO, dir, adev,
+                           &amdgpu_ras_debugfs_eeprom_size_ops);
+       con->de_ras_eeprom_table = debugfs_create_file("ras_eeprom_table",
+                                                      S_IRUGO, dir, adev,
+                                                      &amdgpu_ras_debugfs_eeprom_table_ops);
+       amdgpu_ras_debugfs_set_ret_size(&con->eeprom_control);
 
        /*
         * After one uncorrectable error happens, usually GPU recovery will
@@ -1833,13 +1843,12 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev)
 
        control = &con->eeprom_control;
        data = con->eh_data;
-       save_count = data->count - control->num_recs;
+       save_count = data->count - control->ras_num_recs;
        /* only new entries are saved */
        if (save_count > 0) {
-               if (amdgpu_ras_eeprom_process_recods(control,
-                                                       &data->bps[control->num_recs],
-                                                       true,
-                                                       save_count)) {
+               if (amdgpu_ras_eeprom_append(control,
+                                            &data->bps[control->ras_num_recs],
+                                            save_count)) {
                        dev_err(adev->dev, "Failed to save EEPROM table data!");
                        return -EIO;
                }
@@ -1857,28 +1866,24 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev)
 static int amdgpu_ras_load_bad_pages(struct amdgpu_device *adev)
 {
        struct amdgpu_ras_eeprom_control *control =
-                                       &adev->psp.ras.ras->eeprom_control;
-       struct eeprom_table_record *bps = NULL;
-       int ret = 0;
+               &adev->psp.ras.ras->eeprom_control;
+       struct eeprom_table_record *bps;
+       int ret;
 
        /* no bad page record, skip eeprom access */
-       if (!control->num_recs || (amdgpu_bad_page_threshold == 0))
-               return ret;
+       if (control->ras_num_recs == 0 || amdgpu_bad_page_threshold == 0)
+               return 0;
 
-       bps = kcalloc(control->num_recs, sizeof(*bps), GFP_KERNEL);
+       bps = kcalloc(control->ras_num_recs, sizeof(*bps), GFP_KERNEL);
        if (!bps)
                return -ENOMEM;
 
-       if (amdgpu_ras_eeprom_process_recods(control, bps, false,
-               control->num_recs)) {
+       ret = amdgpu_ras_eeprom_read(control, bps, control->ras_num_recs);
+       if (ret)
                dev_err(adev->dev, "Failed to load EEPROM table records!");
-               ret = -EIO;
-               goto out;
-       }
-
-       ret = amdgpu_ras_add_bad_pages(adev, bps, control->num_recs);
+       else
+               ret = amdgpu_ras_add_bad_pages(adev, bps, control->ras_num_recs);
 
-out:
        kfree(bps);
        return ret;
 }
@@ -1918,11 +1923,9 @@ static bool amdgpu_ras_check_bad_page(struct amdgpu_device *adev,
 }
 
 static void amdgpu_ras_validate_threshold(struct amdgpu_device *adev,
-                                       uint32_t max_length)
+                                         uint32_t max_count)
 {
        struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
-       int tmp_threshold = amdgpu_bad_page_threshold;
-       u64 val;
 
        /*
         * Justification of value bad_page_cnt_threshold in ras structure
@@ -1943,18 +1946,15 @@ static void amdgpu_ras_validate_threshold(struct amdgpu_device *adev,
         *      take no effect.
         */
 
-       if (tmp_threshold < -1)
-               tmp_threshold = -1;
-       else if (tmp_threshold > max_length)
-               tmp_threshold = max_length;
+       if (amdgpu_bad_page_threshold < 0) {
+               u64 val = adev->gmc.mc_vram_size;
 
-       if (tmp_threshold == -1) {
-               val = adev->gmc.mc_vram_size;
-               do_div(val, RAS_BAD_PAGE_RATE);
+               do_div(val, RAS_BAD_PAGE_COVER);
                con->bad_page_cnt_threshold = min(lower_32_bits(val),
-                                               max_length);
+                                                 max_count);
        } else {
-               con->bad_page_cnt_threshold = tmp_threshold;
+               con->bad_page_cnt_threshold = min_t(int, max_count,
+                                                   amdgpu_bad_page_threshold);
        }
 }
 
@@ -1962,15 +1962,24 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
 {
        struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
        struct ras_err_handler_data **data;
-       uint32_t max_eeprom_records_len = 0;
+       u32  max_eeprom_records_count = 0;
        bool exc_err_limit = false;
        int ret;
 
-       if (adev->ras_enabled && con)
-               data = &con->eh_data;
-       else
+       if (!con)
                return 0;
 
+       /* Allow access to RAS EEPROM via debugfs, when the ASIC
+        * supports RAS and debugfs is enabled, but when
+        * adev->ras_enabled is unset, i.e. when "ras_enable"
+        * module parameter is set to 0.
+        */
+       con->adev = adev;
+
+       if (!adev->ras_enabled)
+               return 0;
+
+       data = &con->eh_data;
        *data = kmalloc(sizeof(**data), GFP_KERNEL | __GFP_ZERO);
        if (!*data) {
                ret = -ENOMEM;
@@ -1980,10 +1989,9 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
        mutex_init(&con->recovery_lock);
        INIT_WORK(&con->recovery_work, amdgpu_ras_do_recovery);
        atomic_set(&con->in_recovery, 0);
-       con->adev = adev;
 
-       max_eeprom_records_len = amdgpu_ras_eeprom_get_record_max_length();
-       amdgpu_ras_validate_threshold(adev, max_eeprom_records_len);
+       max_eeprom_records_count = amdgpu_ras_eeprom_max_record_count();
+       amdgpu_ras_validate_threshold(adev, max_eeprom_records_count);
 
        /* Todo: During test the SMU might fail to read the eeprom through I2C
         * when the GPU is pending on XGMI reset during probe time
@@ -1999,13 +2007,13 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
        if (exc_err_limit || ret)
                goto free;
 
-       if (con->eeprom_control.num_recs) {
+       if (con->eeprom_control.ras_num_recs) {
                ret = amdgpu_ras_load_bad_pages(adev);
                if (ret)
                        goto free;
 
                if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->send_hbm_bad_pages_num)
-                       adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.num_recs);
+                       adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.ras_num_recs);
        }
 
        return 0;
@@ -2015,7 +2023,7 @@ free:
        kfree(*data);
        con->eh_data = NULL;
 out:
-       dev_warn(adev->dev, "Failed to initialize ras recovery!\n");
+       dev_warn(adev->dev, "Failed to initialize ras recovery! (%d)\n", ret);
 
        /*
         * Except error threshold exceeding case, other failure cases in this
index b504ed8c9b50be8cf5064694582d53e5158c81e7..4d9c63f2f37718e18b75b90fb8dc32a4b8a2056f 100644 (file)
@@ -318,6 +318,7 @@ struct amdgpu_ras {
        /* sysfs */
        struct device_attribute features_attr;
        struct bin_attribute badpages_attr;
+       struct dentry *de_ras_eeprom_table;
        /* block array */
        struct ras_manager *objs;
 
index f40c871da0c623d584953d23b292b5772f91432f..d2e5b2567bc1bc9779df90a35dd88788ad682d4d 100644 (file)
 #include "amdgpu_ras.h"
 #include <linux/bits.h>
 #include "atom.h"
+#include "amdgpu_eeprom.h"
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
 
-#define EEPROM_I2C_TARGET_ADDR_VEGA20          0xA0
-#define EEPROM_I2C_TARGET_ADDR_ARCTURUS                0xA8
-#define EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342   0xA0
-#define EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID   0xA0
-#define EEPROM_I2C_TARGET_ADDR_ALDEBARAN        0xA0
+#define EEPROM_I2C_MADDR_VEGA20         0x0
+#define EEPROM_I2C_MADDR_ARCTURUS       0x40000
+#define EEPROM_I2C_MADDR_ARCTURUS_D342  0x0
+#define EEPROM_I2C_MADDR_SIENNA_CICHLID 0x0
+#define EEPROM_I2C_MADDR_ALDEBARAN      0x0
 
 /*
  * The 2 macros bellow represent the actual size in bytes that
  * those entities occupy in the EEPROM memory.
- * EEPROM_TABLE_RECORD_SIZE is different than sizeof(eeprom_table_record) which
+ * RAS_TABLE_RECORD_SIZE is different than sizeof(eeprom_table_record) which
  * uses uint64 to store 6b fields such as retired_page.
  */
-#define EEPROM_TABLE_HEADER_SIZE 20
-#define EEPROM_TABLE_RECORD_SIZE 24
-
-#define EEPROM_ADDRESS_SIZE 0x2
+#define RAS_TABLE_HEADER_SIZE   20
+#define RAS_TABLE_RECORD_SIZE   24
 
 /* Table hdr is 'AMDR' */
-#define EEPROM_TABLE_HDR_VAL 0x414d4452
-#define EEPROM_TABLE_VER 0x00010000
+#define RAS_TABLE_HDR_VAL       0x414d4452
+#define RAS_TABLE_VER           0x00010000
 
 /* Bad GPU tag â€˜BADG’ */
-#define EEPROM_TABLE_HDR_BAD 0x42414447
+#define RAS_TABLE_HDR_BAD       0x42414447
+
+/* Assume 2-Mbit size EEPROM and take up the whole space. */
+#define RAS_TBL_SIZE_BYTES      (256 * 1024)
+#define RAS_TABLE_START         0
+#define RAS_HDR_START           RAS_TABLE_START
+#define RAS_RECORD_START        (RAS_HDR_START + RAS_TABLE_HEADER_SIZE)
+#define RAS_MAX_RECORD_COUNT    ((RAS_TBL_SIZE_BYTES - RAS_TABLE_HEADER_SIZE) \
+                                / RAS_TABLE_RECORD_SIZE)
+
+/* Given a zero-based index of an EEPROM RAS record, yields the EEPROM
+ * offset off of RAS_TABLE_START.  That is, this is something you can
+ * add to control->i2c_address, and then tell I2C layer to read
+ * from/write to there. _N is the so called absolute index,
+ * because it starts right after the table header.
+ */
+#define RAS_INDEX_TO_OFFSET(_C, _N) ((_C)->ras_record_offset + \
+                                    (_N) * RAS_TABLE_RECORD_SIZE)
+
+#define RAS_OFFSET_TO_INDEX(_C, _O) (((_O) - \
+                                     (_C)->ras_record_offset) / RAS_TABLE_RECORD_SIZE)
+
+/* Given a 0-based relative record index, 0, 1, 2, ..., etc., off
+ * of "fri", return the absolute record index off of the end of
+ * the table header.
+ */
+#define RAS_RI_TO_AI(_C, _I) (((_I) + (_C)->ras_fri) % \
+                             (_C)->ras_max_record_count)
 
-/* Assume 2 Mbit size */
-#define EEPROM_SIZE_BYTES 256000
-#define EEPROM_PAGE__SIZE_BYTES 256
-#define EEPROM_HDR_START 0
-#define EEPROM_RECORD_START (EEPROM_HDR_START + EEPROM_TABLE_HEADER_SIZE)
-#define EEPROM_MAX_RECORD_NUM ((EEPROM_SIZE_BYTES - EEPROM_TABLE_HEADER_SIZE) / EEPROM_TABLE_RECORD_SIZE)
-#define EEPROM_ADDR_MSB_MASK GENMASK(17, 8)
+#define RAS_NUM_RECS(_tbl_hdr)  (((_tbl_hdr)->tbl_size - \
+                                 RAS_TABLE_HEADER_SIZE) / RAS_TABLE_RECORD_SIZE)
 
 #define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, eeprom_control))->adev
 
 static bool __is_ras_eeprom_supported(struct amdgpu_device *adev)
 {
-       if ((adev->asic_type == CHIP_VEGA20) ||
-           (adev->asic_type == CHIP_ARCTURUS) ||
-           (adev->asic_type == CHIP_SIENNA_CICHLID) ||
-           (adev->asic_type == CHIP_ALDEBARAN))
-               return true;
-
-       return false;
+       return  adev->asic_type == CHIP_VEGA20 ||
+               adev->asic_type == CHIP_ARCTURUS ||
+               adev->asic_type == CHIP_SIENNA_CICHLID ||
+               adev->asic_type == CHIP_ALDEBARAN;
 }
 
 static bool __get_eeprom_i2c_addr_arct(struct amdgpu_device *adev,
-                                      uint16_t *i2c_addr)
+                                      struct amdgpu_ras_eeprom_control *control)
 {
        struct atom_context *atom_ctx = adev->mode_info.atom_context;
 
-       if (!i2c_addr || !atom_ctx)
+       if (!control || !atom_ctx)
                return false;
 
        if (strnstr(atom_ctx->vbios_version,
                    "D342",
                    sizeof(atom_ctx->vbios_version)))
-               *i2c_addr = EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342;
+               control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS_D342;
        else
-               *i2c_addr = EEPROM_I2C_TARGET_ADDR_ARCTURUS;
+               control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS;
 
        return true;
 }
 
 static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
-                                 uint16_t *i2c_addr)
+                                 struct amdgpu_ras_eeprom_control *control)
 {
-       if (!i2c_addr)
+       if (!control)
                return false;
 
        switch (adev->asic_type) {
        case CHIP_VEGA20:
-               *i2c_addr = EEPROM_I2C_TARGET_ADDR_VEGA20;
+               control->i2c_address = EEPROM_I2C_MADDR_VEGA20;
                break;
 
        case CHIP_ARCTURUS:
-               return __get_eeprom_i2c_addr_arct(adev, i2c_addr);
+               return __get_eeprom_i2c_addr_arct(adev, control);
 
        case CHIP_SIENNA_CICHLID:
-               *i2c_addr = EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID;
+               control->i2c_address = EEPROM_I2C_MADDR_SIENNA_CICHLID;
                break;
 
        case CHIP_ALDEBARAN:
-               *i2c_addr = EEPROM_I2C_TARGET_ADDR_ALDEBARAN;
+               control->i2c_address = EEPROM_I2C_MADDR_ALDEBARAN;
                break;
 
        default:
@@ -119,10 +139,11 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
        return true;
 }
 
-static void __encode_table_header_to_buff(struct amdgpu_ras_eeprom_table_header *hdr,
-                                         unsigned char *buff)
+static void
+__encode_table_header_to_buf(struct amdgpu_ras_eeprom_table_header *hdr,
+                            unsigned char *buf)
 {
-       uint32_t *pp = (uint32_t *) buff;
+       u32 *pp = (uint32_t *)buf;
 
        pp[0] = cpu_to_le32(hdr->header);
        pp[1] = cpu_to_le32(hdr->version);
@@ -131,10 +152,11 @@ static void __encode_table_header_to_buff(struct amdgpu_ras_eeprom_table_header
        pp[4] = cpu_to_le32(hdr->checksum);
 }
 
-static void __decode_table_header_from_buff(struct amdgpu_ras_eeprom_table_header *hdr,
-                                         unsigned char *buff)
+static void
+__decode_table_header_from_buf(struct amdgpu_ras_eeprom_table_header *hdr,
+                              unsigned char *buf)
 {
-       uint32_t *pp = (uint32_t *)buff;
+       u32 *pp = (uint32_t *)buf;
 
        hdr->header           = le32_to_cpu(pp[0]);
        hdr->version          = le32_to_cpu(pp[1]);
@@ -143,303 +165,168 @@ static void __decode_table_header_from_buff(struct amdgpu_ras_eeprom_table_heade
        hdr->checksum         = le32_to_cpu(pp[4]);
 }
 
-static int __update_table_header(struct amdgpu_ras_eeprom_control *control,
-                                unsigned char *buff)
+static int __write_table_header(struct amdgpu_ras_eeprom_control *control)
 {
-       int ret = 0;
+       u8 buf[RAS_TABLE_HEADER_SIZE];
        struct amdgpu_device *adev = to_amdgpu_device(control);
-       struct i2c_msg msg = {
-                       .addr   = 0,
-                       .flags  = 0,
-                       .len    = EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE,
-                       .buf    = buff,
-       };
+       int res;
 
-
-       *(uint16_t *)buff = EEPROM_HDR_START;
-       __encode_table_header_to_buff(&control->tbl_hdr, buff + EEPROM_ADDRESS_SIZE);
-
-       msg.addr = control->i2c_address;
+       memset(buf, 0, sizeof(buf));
+       __encode_table_header_to_buf(&control->tbl_hdr, buf);
 
        /* i2c may be unstable in gpu reset */
        down_read(&adev->reset_sem);
-       ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1);
+       res = amdgpu_eeprom_write(&adev->pm.smu_i2c,
+                                 control->i2c_address +
+                                 control->ras_header_offset,
+                                 buf, RAS_TABLE_HEADER_SIZE);
        up_read(&adev->reset_sem);
 
-       if (ret < 1)
-               DRM_ERROR("Failed to write EEPROM table header, ret:%d", ret);
-
-       return ret;
-}
-
-static uint32_t  __calc_hdr_byte_sum(struct amdgpu_ras_eeprom_control *control)
-{
-       int i;
-       uint32_t tbl_sum = 0;
-
-       /* Header checksum, skip checksum field in the calculation */
-       for (i = 0; i < sizeof(control->tbl_hdr) - sizeof(control->tbl_hdr.checksum); i++)
-               tbl_sum += *(((unsigned char *)&control->tbl_hdr) + i);
-
-       return tbl_sum;
-}
-
-static uint32_t  __calc_recs_byte_sum(struct eeprom_table_record *records,
-                                     int num)
-{
-       int i, j;
-       uint32_t tbl_sum = 0;
-
-       /* Records checksum */
-       for (i = 0; i < num; i++) {
-               struct eeprom_table_record *record = &records[i];
-
-               for (j = 0; j < sizeof(*record); j++) {
-                       tbl_sum += *(((unsigned char *)record) + j);
-               }
+       if (res < 0) {
+               DRM_ERROR("Failed to write EEPROM table header:%d", res);
+       } else if (res < RAS_TABLE_HEADER_SIZE) {
+               DRM_ERROR("Short write:%d out of %d\n",
+                         res, RAS_TABLE_HEADER_SIZE);
+               res = -EIO;
+       } else {
+               res = 0;
        }
 
-       return tbl_sum;
+       return res;
 }
 
-static inline uint32_t  __calc_tbl_byte_sum(struct amdgpu_ras_eeprom_control *control,
-                                 struct eeprom_table_record *records, int num)
+static u8 __calc_hdr_byte_sum(const struct amdgpu_ras_eeprom_control *control)
 {
-       return __calc_hdr_byte_sum(control) + __calc_recs_byte_sum(records, num);
-}
+       int ii;
+       u8  *pp, csum;
+       size_t sz;
 
-/* Checksum = 256 -((sum of all table entries) mod 256) */
-static void __update_tbl_checksum(struct amdgpu_ras_eeprom_control *control,
-                                 struct eeprom_table_record *records, int num,
-                                 uint32_t old_hdr_byte_sum)
-{
-       /*
-        * This will update the table sum with new records.
-        *
-        * TODO: What happens when the EEPROM table is to be wrapped around
-        * and old records from start will get overridden.
-        */
-
-       /* need to recalculate updated header byte sum */
-       control->tbl_byte_sum -= old_hdr_byte_sum;
-       control->tbl_byte_sum += __calc_tbl_byte_sum(control, records, num);
-
-       control->tbl_hdr.checksum = 256 - (control->tbl_byte_sum % 256);
-}
-
-/* table sum mod 256 + checksum must equals 256 */
-static bool __validate_tbl_checksum(struct amdgpu_ras_eeprom_control *control,
-                           struct eeprom_table_record *records, int num)
-{
-       control->tbl_byte_sum = __calc_tbl_byte_sum(control, records, num);
-
-       if (control->tbl_hdr.checksum + (control->tbl_byte_sum % 256) != 256) {
-               DRM_WARN("Checksum mismatch, checksum: %u ", control->tbl_hdr.checksum);
-               return false;
-       }
+       /* Header checksum, skip checksum field in the calculation */
+       sz = sizeof(control->tbl_hdr) - sizeof(control->tbl_hdr.checksum);
+       pp = (u8 *) &control->tbl_hdr;
+       csum = 0;
+       for (ii = 0; ii < sz; ii++, pp++)
+               csum += *pp;
 
-       return true;
+       return csum;
 }
 
 static int amdgpu_ras_eeprom_correct_header_tag(
-                               struct amdgpu_ras_eeprom_control *control,
-                               uint32_t header)
+       struct amdgpu_ras_eeprom_control *control,
+       uint32_t header)
 {
-       unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE];
        struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
-       int ret = 0;
-
-       memset(buff, 0, EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE);
-
-       mutex_lock(&control->tbl_mutex);
+       u8 *hh;
+       int res;
+       u8 csum;
+
+       csum = -hdr->checksum;
+
+       hh = (void *) &hdr->header;
+       csum -= (hh[0] + hh[1] + hh[2] + hh[3]);
+       hh = (void *) &header;
+       csum += hh[0] + hh[1] + hh[2] + hh[3];
+       csum = -csum;
+       mutex_lock(&control->ras_tbl_mutex);
        hdr->header = header;
-       ret = __update_table_header(control, buff);
-       mutex_unlock(&control->tbl_mutex);
+       hdr->checksum = csum;
+       res = __write_table_header(control);
+       mutex_unlock(&control->ras_tbl_mutex);
 
-       return ret;
+       return res;
 }
 
+/**
+ * amdgpu_ras_eeprom_reset_table -- Reset the RAS EEPROM table
+ * @control: pointer to control structure
+ *
+ * Reset the contents of the header of the RAS EEPROM table.
+ * Return 0 on success, -errno on error.
+ */
 int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control)
 {
-       unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE] = { 0 };
        struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
-       int ret = 0;
+       u8 csum;
+       int res;
 
-       mutex_lock(&control->tbl_mutex);
+       mutex_lock(&control->ras_tbl_mutex);
 
-       hdr->header = EEPROM_TABLE_HDR_VAL;
-       hdr->version = EEPROM_TABLE_VER;
-       hdr->first_rec_offset = EEPROM_RECORD_START;
-       hdr->tbl_size = EEPROM_TABLE_HEADER_SIZE;
+       hdr->header = RAS_TABLE_HDR_VAL;
+       hdr->version = RAS_TABLE_VER;
+       hdr->first_rec_offset = RAS_RECORD_START;
+       hdr->tbl_size = RAS_TABLE_HEADER_SIZE;
 
-       control->tbl_byte_sum = 0;
-       __update_tbl_checksum(control, NULL, 0, 0);
-       control->next_addr = EEPROM_RECORD_START;
+       csum = __calc_hdr_byte_sum(control);
+       csum = -csum;
+       hdr->checksum = csum;
+       res = __write_table_header(control);
 
-       ret = __update_table_header(control, buff);
+       control->ras_num_recs = 0;
+       control->ras_fri = 0;
 
-       mutex_unlock(&control->tbl_mutex);
+       amdgpu_ras_debugfs_set_ret_size(control);
 
-       return ret;
+       mutex_unlock(&control->ras_tbl_mutex);
 
+       return res;
 }
 
-int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
-                       bool *exceed_err_limit)
-{
-       int ret = 0;
-       struct amdgpu_device *adev = to_amdgpu_device(control);
-       unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE] = { 0 };
-       struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
-       struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
-       struct i2c_msg msg = {
-                       .addr   = 0,
-                       .flags  = I2C_M_RD,
-                       .len    = EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE,
-                       .buf    = buff,
-       };
-
-       *exceed_err_limit = false;
-
-       if (!__is_ras_eeprom_supported(adev))
-               return 0;
-
-       /* Verify i2c adapter is initialized */
-       if (!adev->pm.smu_i2c.algo)
-               return -ENOENT;
-
-       if (!__get_eeprom_i2c_addr(adev, &control->i2c_address))
-               return -EINVAL;
-
-       mutex_init(&control->tbl_mutex);
-
-       msg.addr = control->i2c_address;
-       /* Read/Create table header from EEPROM address 0 */
-       ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1);
-       if (ret < 1) {
-               DRM_ERROR("Failed to read EEPROM table header, ret:%d", ret);
-               return ret;
-       }
-
-       __decode_table_header_from_buff(hdr, &buff[2]);
-
-       if (hdr->header == EEPROM_TABLE_HDR_VAL) {
-               control->num_recs = (hdr->tbl_size - EEPROM_TABLE_HEADER_SIZE) /
-                                   EEPROM_TABLE_RECORD_SIZE;
-               control->tbl_byte_sum = __calc_hdr_byte_sum(control);
-               control->next_addr = EEPROM_RECORD_START;
-
-               DRM_DEBUG_DRIVER("Found existing EEPROM table with %d records",
-                                control->num_recs);
-
-       } else if ((hdr->header == EEPROM_TABLE_HDR_BAD) &&
-                       (amdgpu_bad_page_threshold != 0)) {
-               if (ras->bad_page_cnt_threshold > control->num_recs) {
-                       dev_info(adev->dev, "Using one valid bigger bad page "
-                               "threshold and correcting eeprom header tag.\n");
-                       ret = amdgpu_ras_eeprom_correct_header_tag(control,
-                                                       EEPROM_TABLE_HDR_VAL);
-               } else {
-                       *exceed_err_limit = true;
-                       dev_err(adev->dev, "Exceeding the bad_page_threshold parameter, "
-                               "disabling the GPU.\n");
-               }
-       } else {
-               DRM_INFO("Creating new EEPROM table");
-
-               ret = amdgpu_ras_eeprom_reset_table(control);
-       }
-
-       return ret == 1 ? 0 : -EIO;
-}
-
-static void __encode_table_record_to_buff(struct amdgpu_ras_eeprom_control *control,
-                                         struct eeprom_table_record *record,
-                                         unsigned char *buff)
+static void
+__encode_table_record_to_buf(struct amdgpu_ras_eeprom_control *control,
+                            struct eeprom_table_record *record,
+                            unsigned char *buf)
 {
        __le64 tmp = 0;
        int i = 0;
 
        /* Next are all record fields according to EEPROM page spec in LE foramt */
-       buff[i++] = record->err_type;
+       buf[i++] = record->err_type;
 
-       buff[i++] = record->bank;
+       buf[i++] = record->bank;
 
        tmp = cpu_to_le64(record->ts);
-       memcpy(buff + i, &tmp, 8);
+       memcpy(buf + i, &tmp, 8);
        i += 8;
 
        tmp = cpu_to_le64((record->offset & 0xffffffffffff));
-       memcpy(buff + i, &tmp, 6);
+       memcpy(buf + i, &tmp, 6);
        i += 6;
 
-       buff[i++] = record->mem_channel;
-       buff[i++] = record->mcumc_id;
+       buf[i++] = record->mem_channel;
+       buf[i++] = record->mcumc_id;
 
        tmp = cpu_to_le64((record->retired_page & 0xffffffffffff));
-       memcpy(buff + i, &tmp, 6);
+       memcpy(buf + i, &tmp, 6);
 }
 
-static void __decode_table_record_from_buff(struct amdgpu_ras_eeprom_control *control,
-                                           struct eeprom_table_record *record,
-                                           unsigned char *buff)
+static void
+__decode_table_record_from_buf(struct amdgpu_ras_eeprom_control *control,
+                              struct eeprom_table_record *record,
+                              unsigned char *buf)
 {
        __le64 tmp = 0;
        int i =  0;
 
        /* Next are all record fields according to EEPROM page spec in LE foramt */
-       record->err_type = buff[i++];
+       record->err_type = buf[i++];
 
-       record->bank = buff[i++];
+       record->bank = buf[i++];
 
-       memcpy(&tmp, buff + i, 8);
+       memcpy(&tmp, buf + i, 8);
        record->ts = le64_to_cpu(tmp);
        i += 8;
 
-       memcpy(&tmp, buff + i, 6);
+       memcpy(&tmp, buf + i, 6);
        record->offset = (le64_to_cpu(tmp) & 0xffffffffffff);
        i += 6;
 
-       record->mem_channel = buff[i++];
-       record->mcumc_id = buff[i++];
+       record->mem_channel = buf[i++];
+       record->mcumc_id = buf[i++];
 
-       memcpy(&tmp, buff + i,  6);
+       memcpy(&tmp, buf + i,  6);
        record->retired_page = (le64_to_cpu(tmp) & 0xffffffffffff);
 }
 
-/*
- * When reaching end of EEPROM memory jump back to 0 record address
- * When next record access will go beyond EEPROM page boundary modify bits A17/A8
- * in I2C selector to go to next page
- */
-static uint32_t __correct_eeprom_dest_address(uint32_t curr_address)
-{
-       uint32_t next_address = curr_address + EEPROM_TABLE_RECORD_SIZE;
-
-       /* When all EEPROM memory used jump back to 0 address */
-       if (next_address > EEPROM_SIZE_BYTES) {
-               DRM_INFO("Reached end of EEPROM memory, jumping to 0 "
-                        "and overriding old record");
-               return EEPROM_RECORD_START;
-       }
-
-       /*
-        * To check if we overflow page boundary  compare next address with
-        * current and see if bits 17/8 of the EEPROM address will change
-        * If they do start from the next 256b page
-        *
-        * https://www.st.com/resource/en/datasheet/m24m02-dr.pdf sec. 5.1.2
-        */
-       if ((curr_address & EEPROM_ADDR_MSB_MASK) != (next_address & EEPROM_ADDR_MSB_MASK)) {
-               DRM_DEBUG_DRIVER("Reached end of EEPROM memory page, jumping to next: %lx",
-                               (next_address & EEPROM_ADDR_MSB_MASK));
-
-               return  (next_address & EEPROM_ADDR_MSB_MASK);
-       }
-
-       return curr_address;
-}
-
 bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev)
 {
        struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
@@ -454,197 +341,756 @@ bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev)
                if (!(con->features & BIT(AMDGPU_RAS_BLOCK__UMC)))
                        return false;
 
-       if (con->eeprom_control.tbl_hdr.header == EEPROM_TABLE_HDR_BAD) {
+       if (con->eeprom_control.tbl_hdr.header == RAS_TABLE_HDR_BAD) {
                dev_warn(adev->dev, "This GPU is in BAD status.");
-               dev_warn(adev->dev, "Please retire it or setting one bigger "
-                               "threshold value when reloading driver.\n");
+               dev_warn(adev->dev, "Please retire it or set a larger "
+                        "threshold value when reloading driver.\n");
                return true;
        }
 
        return false;
 }
 
-int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
-                                           struct eeprom_table_record *records,
-                                           bool write,
-                                           int num)
+/**
+ * __amdgpu_ras_eeprom_write -- write indexed from buffer to EEPROM
+ * @control: pointer to control structure
+ * @buf: pointer to buffer containing data to write
+ * @fri: start writing at this index
+ * @num: number of records to write
+ *
+ * The caller must hold the table mutex in @control.
+ * Return 0 on success, -errno otherwise.
+ */
+static int __amdgpu_ras_eeprom_write(struct amdgpu_ras_eeprom_control *control,
+                                    u8 *buf, const u32 fri, const u32 num)
 {
-       int i, ret = 0;
-       struct i2c_msg *msgs, *msg;
-       unsigned char *buffs, *buff;
-       struct eeprom_table_record *record;
        struct amdgpu_device *adev = to_amdgpu_device(control);
-       struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+       u32 buf_size;
+       int res;
 
-       if (!__is_ras_eeprom_supported(adev))
-               return 0;
+       /* i2c may be unstable in gpu reset */
+       down_read(&adev->reset_sem);
+       buf_size = num * RAS_TABLE_RECORD_SIZE;
+       res = amdgpu_eeprom_write(&adev->pm.smu_i2c,
+                                 control->i2c_address +
+                                 RAS_INDEX_TO_OFFSET(control, fri),
+                                 buf, buf_size);
+       up_read(&adev->reset_sem);
+       if (res < 0) {
+               DRM_ERROR("Writing %d EEPROM table records error:%d",
+                         num, res);
+       } else if (res < buf_size) {
+               /* Short write, return error.
+                */
+               DRM_ERROR("Wrote %d records out of %d",
+                         res / RAS_TABLE_RECORD_SIZE, num);
+               res = -EIO;
+       } else {
+               res = 0;
+       }
 
-       buffs = kcalloc(num, EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE,
-                        GFP_KERNEL);
-       if (!buffs)
-               return -ENOMEM;
+       return res;
+}
+
+static int
+amdgpu_ras_eeprom_append_table(struct amdgpu_ras_eeprom_control *control,
+                              struct eeprom_table_record *record,
+                              const u32 num)
+{
+       u32 a, b, i;
+       u8 *buf, *pp;
+       int res;
 
-       mutex_lock(&control->tbl_mutex);
+       buf = kcalloc(num, RAS_TABLE_RECORD_SIZE, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
 
-       msgs = kcalloc(num, sizeof(*msgs), GFP_KERNEL);
-       if (!msgs) {
-               ret = -ENOMEM;
-               goto free_buff;
+       /* Encode all of them in one go.
+        */
+       pp = buf;
+       for (i = 0; i < num; i++, pp += RAS_TABLE_RECORD_SIZE)
+               __encode_table_record_to_buf(control, &record[i], pp);
+
+       /* a, first record index to write into.
+        * b, last record index to write into.
+        * a = first index to read (fri) + number of records in the table,
+        * b = a + @num - 1.
+        * Let N = control->ras_max_num_record_count, then we have,
+        * case 0: 0 <= a <= b < N,
+        *   just append @num records starting at a;
+        * case 1: 0 <= a < N <= b,
+        *   append (N - a) records starting at a, and
+        *   append the remainder,  b % N + 1, starting at 0.
+        * case 2: 0 <= fri < N <= a <= b, then modulo N we get two subcases,
+        * case 2a: 0 <= a <= b < N
+        *   append num records starting at a; and fix fri if b overwrote it,
+        *   and since a <= b, if b overwrote it then a must've also,
+        *   and if b didn't overwrite it, then a didn't also.
+        * case 2b: 0 <= b < a < N
+        *   write num records starting at a, which wraps around 0=N
+        *   and overwrite fri unconditionally. Now from case 2a,
+        *   this means that b eclipsed fri to overwrite it and wrap
+        *   around 0 again, i.e. b = 2N+r pre modulo N, so we unconditionally
+        *   set fri = b + 1 (mod N).
+        * Now, since fri is updated in every case, except the trivial case 0,
+        * the number of records present in the table after writing, is,
+        * num_recs - 1 = b - fri (mod N), and we take the positive value,
+        * by adding an arbitrary multiple of N before taking the modulo N
+        * as shown below.
+        */
+       a = control->ras_fri + control->ras_num_recs;
+       b = a + num  - 1;
+       if (b < control->ras_max_record_count) {
+               res = __amdgpu_ras_eeprom_write(control, buf, a, num);
+       } else if (a < control->ras_max_record_count) {
+               u32 g0, g1;
+
+               g0 = control->ras_max_record_count - a;
+               g1 = b % control->ras_max_record_count + 1;
+               res = __amdgpu_ras_eeprom_write(control, buf, a, g0);
+               if (res)
+                       goto Out;
+               res = __amdgpu_ras_eeprom_write(control,
+                                               buf + g0 * RAS_TABLE_RECORD_SIZE,
+                                               0, g1);
+               if (res)
+                       goto Out;
+               if (g1 > control->ras_fri)
+                       control->ras_fri = g1 % control->ras_max_record_count;
+       } else {
+               a %= control->ras_max_record_count;
+               b %= control->ras_max_record_count;
+
+               if (a <= b) {
+                       /* Note that, b - a + 1 = num. */
+                       res = __amdgpu_ras_eeprom_write(control, buf, a, num);
+                       if (res)
+                               goto Out;
+                       if (b >= control->ras_fri)
+                               control->ras_fri = (b + 1) % control->ras_max_record_count;
+               } else {
+                       u32 g0, g1;
+
+                       /* b < a, which means, we write from
+                        * a to the end of the table, and from
+                        * the start of the table to b.
+                        */
+                       g0 = control->ras_max_record_count - a;
+                       g1 = b + 1;
+                       res = __amdgpu_ras_eeprom_write(control, buf, a, g0);
+                       if (res)
+                               goto Out;
+                       res = __amdgpu_ras_eeprom_write(control,
+                                                       buf + g0 * RAS_TABLE_RECORD_SIZE,
+                                                       0, g1);
+                       if (res)
+                               goto Out;
+                       control->ras_fri = g1 % control->ras_max_record_count;
+               }
        }
+       control->ras_num_recs = 1 + (control->ras_max_record_count + b
+                                    - control->ras_fri)
+               % control->ras_max_record_count;
+Out:
+       kfree(buf);
+       return res;
+}
 
-       /*
-        * If saved bad pages number exceeds the bad page threshold for
-        * the whole VRAM, update table header to mark the BAD GPU tag
-        * and schedule one ras recovery after eeprom write is done,
-        * this can avoid the missing for latest records.
-        *
-        * This new header will be picked up and checked in the bootup
-        * by ras recovery, which may break bootup process to notify
-        * user this GPU is in bad state and to retire such GPU for
-        * further check.
+static int
+amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control)
+{
+       struct amdgpu_device *adev = to_amdgpu_device(control);
+       struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+       u8 *buf, *pp, csum;
+       u32 buf_size;
+       int res;
+
+       /* Modify the header if it exceeds.
         */
-       if (write && (amdgpu_bad_page_threshold != 0) &&
-               ((control->num_recs + num) >= ras->bad_page_cnt_threshold)) {
+       if (amdgpu_bad_page_threshold != 0 &&
+           control->ras_num_recs >= ras->bad_page_cnt_threshold) {
                dev_warn(adev->dev,
-                       "Saved bad pages(%d) reaches threshold value(%d).\n",
-                       control->num_recs + num, ras->bad_page_cnt_threshold);
-               control->tbl_hdr.header = EEPROM_TABLE_HDR_BAD;
+                       "Saved bad pages %d reaches threshold value %d\n",
+                       control->ras_num_recs, ras->bad_page_cnt_threshold);
+               control->tbl_hdr.header = RAS_TABLE_HDR_BAD;
        }
 
-       /* In case of overflow just start from beginning to not lose newest records */
-       if (write && (control->next_addr + EEPROM_TABLE_RECORD_SIZE * num > EEPROM_SIZE_BYTES))
-               control->next_addr = EEPROM_RECORD_START;
+       control->tbl_hdr.version = RAS_TABLE_VER;
+       control->tbl_hdr.first_rec_offset = RAS_INDEX_TO_OFFSET(control, control->ras_fri);
+       control->tbl_hdr.tbl_size = RAS_TABLE_HEADER_SIZE + control->ras_num_recs * RAS_TABLE_RECORD_SIZE;
+       control->tbl_hdr.checksum = 0;
+
+       buf_size = control->ras_num_recs * RAS_TABLE_RECORD_SIZE;
+       buf = kcalloc(control->ras_num_recs, RAS_TABLE_RECORD_SIZE, GFP_KERNEL);
+       if (!buf) {
+               DRM_ERROR("allocating memory for table of size %d bytes failed\n",
+                         control->tbl_hdr.tbl_size);
+               res = -ENOMEM;
+               goto Out;
+       }
 
-       /*
-        * TODO Currently makes EEPROM writes for each record, this creates
-        * internal fragmentation. Optimized the code to do full page write of
-        * 256b
+       down_read(&adev->reset_sem);
+       res = amdgpu_eeprom_read(&adev->pm.smu_i2c,
+                                control->i2c_address +
+                                control->ras_record_offset,
+                                buf, buf_size);
+       up_read(&adev->reset_sem);
+       if (res < 0) {
+               DRM_ERROR("EEPROM failed reading records:%d\n",
+                         res);
+               goto Out;
+       } else if (res < buf_size) {
+               DRM_ERROR("EEPROM read %d out of %d bytes\n",
+                         res, buf_size);
+               res = -EIO;
+               goto Out;
+       }
+
+       /* Recalc the checksum.
         */
-       for (i = 0; i < num; i++) {
-               buff = &buffs[i * (EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE)];
-               record = &records[i];
-               msg = &msgs[i];
+       csum = 0;
+       for (pp = buf; pp < buf + buf_size; pp++)
+               csum += *pp;
+
+       csum += __calc_hdr_byte_sum(control);
+       /* avoid sign extension when assigning to "checksum" */
+       csum = -csum;
+       control->tbl_hdr.checksum = csum;
+       res = __write_table_header(control);
+Out:
+       kfree(buf);
+       return res;
+}
+
+/**
+ * amdgpu_ras_eeprom_append -- append records to the EEPROM RAS table
+ * @control: pointer to control structure
+ * @record: array of records to append
+ * @num: number of records in @record array
+ *
+ * Append @num records to the table, calculate the checksum and write
+ * the table back to EEPROM. The maximum number of records that
+ * can be appended is between 1 and control->ras_max_record_count,
+ * regardless of how many records are already stored in the table.
+ *
+ * Return 0 on success or if EEPROM is not supported, -errno on error.
+ */
+int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control,
+                            struct eeprom_table_record *record,
+                            const u32 num)
+{
+       struct amdgpu_device *adev = to_amdgpu_device(control);
+       int res;
 
-               control->next_addr = __correct_eeprom_dest_address(control->next_addr);
+       if (!__is_ras_eeprom_supported(adev))
+               return 0;
 
-               /*
-                * Update bits 16,17 of EEPROM address in I2C address by setting them
-                * to bits 1,2 of Device address byte
-                */
-               msg->addr = control->i2c_address |
-                               ((control->next_addr & EEPROM_ADDR_MSB_MASK) >> 15);
-               msg->flags      = write ? 0 : I2C_M_RD;
-               msg->len        = EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE;
-               msg->buf        = buff;
-
-               /* Insert the EEPROM dest addess, bits 0-15 */
-               buff[0] = ((control->next_addr >> 8) & 0xff);
-               buff[1] = (control->next_addr & 0xff);
-
-               /* EEPROM table content is stored in LE format */
-               if (write)
-                       __encode_table_record_to_buff(control, record, buff + EEPROM_ADDRESS_SIZE);
-
-               /*
-                * The destination EEPROM address might need to be corrected to account
-                * for page or entire memory wrapping
-                */
-               control->next_addr += EEPROM_TABLE_RECORD_SIZE;
+       if (num == 0) {
+               DRM_ERROR("will not append 0 records\n");
+               return -EINVAL;
+       } else if (num > control->ras_max_record_count) {
+               DRM_ERROR("cannot append %d records than the size of table %d\n",
+                         num, control->ras_max_record_count);
+               return -EINVAL;
        }
 
+       mutex_lock(&control->ras_tbl_mutex);
+
+       res = amdgpu_ras_eeprom_append_table(control, record, num);
+       if (!res)
+               res = amdgpu_ras_eeprom_update_header(control);
+       if (!res)
+               amdgpu_ras_debugfs_set_ret_size(control);
+
+       mutex_unlock(&control->ras_tbl_mutex);
+       return res;
+}
+
+/**
+ * __amdgpu_ras_eeprom_read -- read indexed from EEPROM into buffer
+ * @control: pointer to control structure
+ * @buf: pointer to buffer to read into
+ * @fri: first record index, start reading at this index, absolute index
+ * @num: number of records to read
+ *
+ * The caller must hold the table mutex in @control.
+ * Return 0 on success, -errno otherwise.
+ */
+static int __amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control,
+                                   u8 *buf, const u32 fri, const u32 num)
+{
+       struct amdgpu_device *adev = to_amdgpu_device(control);
+       u32 buf_size;
+       int res;
+
        /* i2c may be unstable in gpu reset */
        down_read(&adev->reset_sem);
-       ret = i2c_transfer(&adev->pm.smu_i2c, msgs, num);
+       buf_size = num * RAS_TABLE_RECORD_SIZE;
+       res = amdgpu_eeprom_read(&adev->pm.smu_i2c,
+                                control->i2c_address +
+                                RAS_INDEX_TO_OFFSET(control, fri),
+                                buf, buf_size);
        up_read(&adev->reset_sem);
+       if (res < 0) {
+               DRM_ERROR("Reading %d EEPROM table records error:%d",
+                         num, res);
+       } else if (res < buf_size) {
+               /* Short read, return error.
+                */
+               DRM_ERROR("Read %d records out of %d",
+                         res / RAS_TABLE_RECORD_SIZE, num);
+               res = -EIO;
+       } else {
+               res = 0;
+       }
 
-       if (ret < 1) {
-               DRM_ERROR("Failed to process EEPROM table records, ret:%d", ret);
+       return res;
+}
 
-               /* TODO Restore prev next EEPROM address ? */
-               goto free_msgs;
+/**
+ * amdgpu_ras_eeprom_read -- read EEPROM
+ * @control: pointer to control structure
+ * @record: array of records to read into
+ * @num: number of records in @record
+ *
+ * Reads num records from the RAS table in EEPROM and
+ * writes the data into @record array.
+ *
+ * Returns 0 on success, -errno on error.
+ */
+int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control,
+                          struct eeprom_table_record *record,
+                          const u32 num)
+{
+       struct amdgpu_device *adev = to_amdgpu_device(control);
+       int i, res;
+       u8 *buf, *pp;
+       u32 g0, g1;
+
+       if (!__is_ras_eeprom_supported(adev))
+               return 0;
+
+       if (num == 0) {
+               DRM_ERROR("will not read 0 records\n");
+               return -EINVAL;
+       } else if (num > control->ras_num_recs) {
+               DRM_ERROR("too many records to read:%d available:%d\n",
+                         num, control->ras_num_recs);
+               return -EINVAL;
        }
 
+       buf = kcalloc(num, RAS_TABLE_RECORD_SIZE, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
 
-       if (!write) {
-               for (i = 0; i < num; i++) {
-                       buff = &buffs[i*(EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE)];
-                       record = &records[i];
+       /* Determine how many records to read, from the first record
+        * index, fri, to the end of the table, and from the beginning
+        * of the table, such that the total number of records is
+        * @num, and we handle wrap around when fri > 0 and
+        * fri + num > RAS_MAX_RECORD_COUNT.
+        *
+        * First we compute the index of the last element
+        * which would be fetched from each region,
+        * g0 is in [fri, fri + num - 1], and
+        * g1 is in [0, RAS_MAX_RECORD_COUNT - 1].
+        * Then, if g0 < RAS_MAX_RECORD_COUNT, the index of
+        * the last element to fetch, we set g0 to _the number_
+        * of elements to fetch, @num, since we know that the last
+        * indexed to be fetched does not exceed the table.
+        *
+        * If, however, g0 >= RAS_MAX_RECORD_COUNT, then
+        * we set g0 to the number of elements to read
+        * until the end of the table, and g1 to the number of
+        * elements to read from the beginning of the table.
+        */
+       g0 = control->ras_fri + num - 1;
+       g1 = g0 % control->ras_max_record_count;
+       if (g0 < control->ras_max_record_count) {
+               g0 = num;
+               g1 = 0;
+       } else {
+               g0 = control->ras_max_record_count - control->ras_fri;
+               g1 += 1;
+       }
 
-                       __decode_table_record_from_buff(control, record, buff + EEPROM_ADDRESS_SIZE);
-               }
+       mutex_lock(&control->ras_tbl_mutex);
+       res = __amdgpu_ras_eeprom_read(control, buf, control->ras_fri, g0);
+       if (res)
+               goto Out;
+       if (g1) {
+               res = __amdgpu_ras_eeprom_read(control,
+                                              buf + g0 * RAS_TABLE_RECORD_SIZE,
+                                              0, g1);
+               if (res)
+                       goto Out;
+       }
+
+       res = 0;
+
+       /* Read up everything? Then transform.
+        */
+       pp = buf;
+       for (i = 0; i < num; i++, pp += RAS_TABLE_RECORD_SIZE)
+               __decode_table_record_from_buf(control, &record[i], pp);
+Out:
+       kfree(buf);
+       mutex_unlock(&control->ras_tbl_mutex);
+
+       return res;
+}
+
+inline uint32_t amdgpu_ras_eeprom_max_record_count(void)
+{
+       return RAS_MAX_RECORD_COUNT;
+}
+
+static ssize_t
+amdgpu_ras_debugfs_eeprom_size_read(struct file *f, char __user *buf,
+                                   size_t size, loff_t *pos)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
+       struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+       struct amdgpu_ras_eeprom_control *control = ras ? &ras->eeprom_control : NULL;
+       u8 data[50];
+       int res;
+
+       if (!size)
+               return size;
+
+       if (!ras || !control) {
+               res = snprintf(data, sizeof(data), "Not supported\n");
+       } else {
+               res = snprintf(data, sizeof(data), "%d bytes or %d records\n",
+                              RAS_TBL_SIZE_BYTES, control->ras_max_record_count);
        }
 
-       if (write) {
-               uint32_t old_hdr_byte_sum = __calc_hdr_byte_sum(control);
+       if (*pos >= res)
+               return 0;
+
+       res -= *pos;
+       res = min_t(size_t, res, size);
 
-               /*
-                * Update table header with size and CRC and account for table
-                * wrap around where the assumption is that we treat it as empty
-                * table
-                *
-                * TODO - Check the assumption is correct
+       if (copy_to_user(buf, &data[*pos], res))
+               return -EFAULT;
+
+       *pos += res;
+
+       return res;
+}
+
+const struct file_operations amdgpu_ras_debugfs_eeprom_size_ops = {
+       .owner = THIS_MODULE,
+       .read = amdgpu_ras_debugfs_eeprom_size_read,
+       .write = NULL,
+       .llseek = default_llseek,
+};
+
+static const char *tbl_hdr_str = " Signature    Version  FirstOffs       Size   Checksum\n";
+static const char *tbl_hdr_fmt = "0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\n";
+#define tbl_hdr_fmt_size (5 * (2+8) + 4 + 1)
+static const char *rec_hdr_str = "Index  Offset ErrType Bank/CU          TimeStamp      Offs/Addr MemChl MCUMCID    RetiredPage\n";
+static const char *rec_hdr_fmt = "%5d 0x%05X %7s    0x%02X 0x%016llX 0x%012llX   0x%02X    0x%02X 0x%012llX\n";
+#define rec_hdr_fmt_size (5 + 1 + 7 + 1 + 7 + 1 + 7 + 1 + 18 + 1 + 14 + 1 + 6 + 1 + 7 + 1 + 14 + 1)
+
+static const char *record_err_type_str[AMDGPU_RAS_EEPROM_ERR_COUNT] = {
+       "ignore",
+       "re",
+       "ue",
+};
+
+static loff_t amdgpu_ras_debugfs_table_size(struct amdgpu_ras_eeprom_control *control)
+{
+       return strlen(tbl_hdr_str) + tbl_hdr_fmt_size +
+               strlen(rec_hdr_str) + rec_hdr_fmt_size * control->ras_num_recs;
+}
+
+void amdgpu_ras_debugfs_set_ret_size(struct amdgpu_ras_eeprom_control *control)
+{
+       struct amdgpu_ras *ras = container_of(control, struct amdgpu_ras,
+                                             eeprom_control);
+       struct dentry *de = ras->de_ras_eeprom_table;
+
+       if (de)
+               d_inode(de)->i_size = amdgpu_ras_debugfs_table_size(control);
+}
+
+static ssize_t amdgpu_ras_debugfs_table_read(struct file *f, char __user *buf,
+                                            size_t size, loff_t *pos)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
+       struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+       struct amdgpu_ras_eeprom_control *control = &ras->eeprom_control;
+       const size_t orig_size = size;
+       int res = -EFAULT;
+       size_t data_len;
+
+       mutex_lock(&control->ras_tbl_mutex);
+
+       /* We want *pos - data_len > 0, which means there's
+        * bytes to be printed from data.
+        */
+       data_len = strlen(tbl_hdr_str);
+       if (*pos < data_len) {
+               data_len -= *pos;
+               data_len = min_t(size_t, data_len, size);
+               if (copy_to_user(buf, &tbl_hdr_str[*pos], data_len))
+                       goto Out;
+               buf += data_len;
+               size -= data_len;
+               *pos += data_len;
+       }
+
+       data_len = strlen(tbl_hdr_str) + tbl_hdr_fmt_size;
+       if (*pos < data_len && size > 0) {
+               u8 data[tbl_hdr_fmt_size + 1];
+               loff_t lpos;
+
+               snprintf(data, sizeof(data), tbl_hdr_fmt,
+                        control->tbl_hdr.header,
+                        control->tbl_hdr.version,
+                        control->tbl_hdr.first_rec_offset,
+                        control->tbl_hdr.tbl_size,
+                        control->tbl_hdr.checksum);
+
+               data_len -= *pos;
+               data_len = min_t(size_t, data_len, size);
+               lpos = *pos - strlen(tbl_hdr_str);
+               if (copy_to_user(buf, &data[lpos], data_len))
+                       goto Out;
+               buf += data_len;
+               size -= data_len;
+               *pos += data_len;
+       }
+
+       data_len = strlen(tbl_hdr_str) + tbl_hdr_fmt_size + strlen(rec_hdr_str);
+       if (*pos < data_len && size > 0) {
+               loff_t lpos;
+
+               data_len -= *pos;
+               data_len = min_t(size_t, data_len, size);
+               lpos = *pos - strlen(tbl_hdr_str) - tbl_hdr_fmt_size;
+               if (copy_to_user(buf, &rec_hdr_str[lpos], data_len))
+                       goto Out;
+               buf += data_len;
+               size -= data_len;
+               *pos += data_len;
+       }
+
+       data_len = amdgpu_ras_debugfs_table_size(control);
+       if (*pos < data_len && size > 0) {
+               u8 dare[RAS_TABLE_RECORD_SIZE];
+               u8 data[rec_hdr_fmt_size + 1];
+               struct eeprom_table_record record;
+               int s, r;
+
+               /* Find the starting record index
                 */
-               control->num_recs += num;
-               control->num_recs %= EEPROM_MAX_RECORD_NUM;
-               control->tbl_hdr.tbl_size += EEPROM_TABLE_RECORD_SIZE * num;
-               if (control->tbl_hdr.tbl_size > EEPROM_SIZE_BYTES)
-                       control->tbl_hdr.tbl_size = EEPROM_TABLE_HEADER_SIZE +
-                       control->num_recs * EEPROM_TABLE_RECORD_SIZE;
-
-               __update_tbl_checksum(control, records, num, old_hdr_byte_sum);
-
-               __update_table_header(control, buffs);
-       } else if (!__validate_tbl_checksum(control, records, num)) {
-               DRM_WARN("EEPROM Table checksum mismatch!");
-               /* TODO Uncomment when EEPROM read/write is relliable */
-               /* ret = -EIO; */
+               s = *pos - strlen(tbl_hdr_str) - tbl_hdr_fmt_size -
+                       strlen(rec_hdr_str);
+               s = s / rec_hdr_fmt_size;
+               r = *pos - strlen(tbl_hdr_str) - tbl_hdr_fmt_size -
+                       strlen(rec_hdr_str);
+               r = r % rec_hdr_fmt_size;
+
+               for ( ; size > 0 && s < control->ras_num_recs; s++) {
+                       u32 ai = RAS_RI_TO_AI(control, s);
+                       /* Read a single record
+                        */
+                       res = __amdgpu_ras_eeprom_read(control, dare, ai, 1);
+                       if (res)
+                               goto Out;
+                       __decode_table_record_from_buf(control, &record, dare);
+                       snprintf(data, sizeof(data), rec_hdr_fmt,
+                                s,
+                                RAS_INDEX_TO_OFFSET(control, ai),
+                                record_err_type_str[record.err_type],
+                                record.bank,
+                                record.ts,
+                                record.offset,
+                                record.mem_channel,
+                                record.mcumc_id,
+                                record.retired_page);
+
+                       data_len = min_t(size_t, rec_hdr_fmt_size - r, size);
+                       if (copy_to_user(buf, &data[r], data_len)) {
+                               res = -EFAULT;
+                               goto Out;
+                       }
+                       buf += data_len;
+                       size -= data_len;
+                       *pos += data_len;
+                       r = 0;
+               }
        }
+       res = 0;
+Out:
+       mutex_unlock(&control->ras_tbl_mutex);
+       return res < 0 ? res : orig_size - size;
+}
 
-free_msgs:
-       kfree(msgs);
+static ssize_t
+amdgpu_ras_debugfs_eeprom_table_read(struct file *f, char __user *buf,
+                                    size_t size, loff_t *pos)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
+       struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+       struct amdgpu_ras_eeprom_control *control = ras ? &ras->eeprom_control : NULL;
+       u8 data[81];
+       int res;
+
+       if (!size)
+               return size;
+
+       if (!ras || !control) {
+               res = snprintf(data, sizeof(data), "Not supported\n");
+               if (*pos >= res)
+                       return 0;
+
+               res -= *pos;
+               res = min_t(size_t, res, size);
 
-free_buff:
-       kfree(buffs);
+               if (copy_to_user(buf, &data[*pos], res))
+                       return -EFAULT;
 
-       mutex_unlock(&control->tbl_mutex);
+               *pos += res;
 
-       return ret == num ? 0 : -EIO;
+               return res;
+       } else {
+               return amdgpu_ras_debugfs_table_read(f, buf, size, pos);
+       }
 }
 
-inline uint32_t amdgpu_ras_eeprom_get_record_max_length(void)
+const struct file_operations amdgpu_ras_debugfs_eeprom_table_ops = {
+       .owner = THIS_MODULE,
+       .read = amdgpu_ras_debugfs_eeprom_table_read,
+       .write = NULL,
+       .llseek = default_llseek,
+};
+
+/**
+ * __verify_ras_table_checksum -- verify the RAS EEPROM table checksum
+ * @control: pointer to control structure
+ *
+ * Check the checksum of the stored in EEPROM RAS table.
+ *
+ * Return 0 if the checksum is correct,
+ * positive if it is not correct, and
+ * -errno on I/O error.
+ */
+static int __verify_ras_table_checksum(struct amdgpu_ras_eeprom_control *control)
 {
-       return EEPROM_MAX_RECORD_NUM;
+       struct amdgpu_device *adev = to_amdgpu_device(control);
+       int buf_size, res;
+       u8  csum, *buf, *pp;
+
+       buf_size = RAS_TABLE_HEADER_SIZE +
+               control->ras_num_recs * RAS_TABLE_RECORD_SIZE;
+       buf = kzalloc(buf_size, GFP_KERNEL);
+       if (!buf) {
+               DRM_ERROR("Out of memory checking RAS table checksum.\n");
+               return -ENOMEM;
+       }
+
+       res = amdgpu_eeprom_read(&adev->pm.smu_i2c,
+                                control->i2c_address +
+                                control->ras_header_offset,
+                                buf, buf_size);
+       if (res < buf_size) {
+               DRM_ERROR("Partial read for checksum, res:%d\n", res);
+               /* On partial reads, return -EIO.
+                */
+               if (res >= 0)
+                       res = -EIO;
+               goto Out;
+       }
+
+       csum = 0;
+       for (pp = buf; pp < buf + buf_size; pp++)
+               csum += *pp;
+Out:
+       kfree(buf);
+       return res < 0 ? res : csum;
 }
 
-/* Used for testing if bugs encountered */
-#if 0
-void amdgpu_ras_eeprom_test(struct amdgpu_ras_eeprom_control *control)
+int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
+                          bool *exceed_err_limit)
 {
-       int i;
-       struct eeprom_table_record *recs = kcalloc(1, sizeof(*recs), GFP_KERNEL);
+       struct amdgpu_device *adev = to_amdgpu_device(control);
+       unsigned char buf[RAS_TABLE_HEADER_SIZE] = { 0 };
+       struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
+       struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+       int res;
+
+       *exceed_err_limit = false;
+
+       if (!__is_ras_eeprom_supported(adev))
+               return 0;
 
-       if (!recs)
-               return;
+       /* Verify i2c adapter is initialized */
+       if (!adev->pm.smu_i2c.algo)
+               return -ENOENT;
 
-       for (i = 0; i < 1 ; i++) {
-               recs[i].address = 0xdeadbeef;
-               recs[i].retired_page = i;
+       if (!__get_eeprom_i2c_addr(adev, control))
+               return -EINVAL;
+
+       control->ras_header_offset = RAS_HDR_START;
+       control->ras_record_offset = RAS_RECORD_START;
+       control->ras_max_record_count  = RAS_MAX_RECORD_COUNT;
+       mutex_init(&control->ras_tbl_mutex);
+
+       /* Read the table header from EEPROM address */
+       res = amdgpu_eeprom_read(&adev->pm.smu_i2c,
+                                control->i2c_address + control->ras_header_offset,
+                                buf, RAS_TABLE_HEADER_SIZE);
+       if (res < RAS_TABLE_HEADER_SIZE) {
+               DRM_ERROR("Failed to read EEPROM table header, res:%d", res);
+               return res >= 0 ? -EIO : res;
        }
 
-       if (!amdgpu_ras_eeprom_process_recods(control, recs, true, 1)) {
+       __decode_table_header_from_buf(hdr, buf);
 
-               memset(recs, 0, sizeof(*recs) * 1);
+       control->ras_num_recs = RAS_NUM_RECS(hdr);
+       control->ras_fri = RAS_OFFSET_TO_INDEX(control, hdr->first_rec_offset);
 
-               control->next_addr = EEPROM_RECORD_START;
+       if (hdr->header == RAS_TABLE_HDR_VAL) {
+               DRM_DEBUG_DRIVER("Found existing EEPROM table with %d records",
+                                control->ras_num_recs);
+               res = __verify_ras_table_checksum(control);
+               if (res)
+                       DRM_ERROR("RAS table incorrect checksum or error:%d\n",
+                                 res);
+       } else if (hdr->header == RAS_TABLE_HDR_BAD &&
+                  amdgpu_bad_page_threshold != 0) {
+               res = __verify_ras_table_checksum(control);
+               if (res)
+                       DRM_ERROR("RAS Table incorrect checksum or error:%d\n",
+                                 res);
+               if (ras->bad_page_cnt_threshold > control->ras_num_recs) {
+                       /* This means that, the threshold was increased since
+                        * the last time the system was booted, and now,
+                        * ras->bad_page_cnt_threshold - control->num_recs > 0,
+                        * so that at least one more record can be saved,
+                        * before the page count threshold is reached.
+                        */
+                       dev_info(adev->dev,
+                                "records:%d threshold:%d, resetting "
+                                "RAS table header signature",
+                                control->ras_num_recs,
+                                ras->bad_page_cnt_threshold);
+                       res = amdgpu_ras_eeprom_correct_header_tag(control,
+                                                                  RAS_TABLE_HDR_VAL);
+               } else {
+                       *exceed_err_limit = true;
+                       dev_err(adev->dev,
+                               "RAS records:%d exceed threshold:%d, "
+                               "maybe retire this GPU?",
+                               control->ras_num_recs, ras->bad_page_cnt_threshold);
+               }
+       } else {
+               DRM_INFO("Creating a new EEPROM table");
 
-               if (!amdgpu_ras_eeprom_process_recods(control, recs, false, 1)) {
-                       for (i = 0; i < 1; i++)
-                               DRM_INFO("rec.address :0x%llx, rec.retired_page :%llu",
-                                        recs[i].address, recs[i].retired_page);
-               } else
-                       DRM_ERROR("Failed in reading from table");
+               res = amdgpu_ras_eeprom_reset_table(control);
+       }
 
-       } else
-               DRM_ERROR("Failed in writing to table");
+       return res < 0 ? res : 0;
 }
-#endif
index 17872117097455a308b6348391eb68e662afc02c..f95fc61b30219c9b6d27a2ff1befe21a41294b32 100644 (file)
 
 struct amdgpu_device;
 
-enum amdgpu_ras_eeprom_err_type{
-       AMDGPU_RAS_EEPROM_ERR_PLACE_HOLDER,
+enum amdgpu_ras_eeprom_err_type {
+       AMDGPU_RAS_EEPROM_ERR_NA,
        AMDGPU_RAS_EEPROM_ERR_RECOVERABLE,
-       AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE
+       AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE,
+       AMDGPU_RAS_EEPROM_ERR_COUNT,
 };
 
 struct amdgpu_ras_eeprom_table_header {
@@ -40,15 +41,45 @@ struct amdgpu_ras_eeprom_table_header {
        uint32_t first_rec_offset;
        uint32_t tbl_size;
        uint32_t checksum;
-}__attribute__((__packed__));
+} __packed;
 
 struct amdgpu_ras_eeprom_control {
        struct amdgpu_ras_eeprom_table_header tbl_hdr;
-       uint32_t next_addr;
-       unsigned int num_recs;
-       struct mutex tbl_mutex;
-       uint32_t tbl_byte_sum;
-       uint16_t i2c_address; // 8-bit represented address
+
+       /* Base I2C EEPPROM 19-bit memory address,
+        * where the table is located. For more information,
+        * see top of amdgpu_eeprom.c.
+        */
+       u32 i2c_address;
+
+       /* The byte offset off of @i2c_address
+        * where the table header is found,
+        * and where the records start--always
+        * right after the header.
+        */
+       u32 ras_header_offset;
+       u32 ras_record_offset;
+
+       /* Number of records in the table.
+        */
+       u32 ras_num_recs;
+
+       /* First record index to read, 0-based.
+        * Range is [0, num_recs-1]. This is
+        * an absolute index, starting right after
+        * the table header.
+        */
+       u32 ras_fri;
+
+       /* Maximum possible number of records
+        * we could store, i.e. the maximum capacity
+        * of the table.
+        */
+       u32 ras_max_record_count;
+
+       /* Protect table access via this mutex.
+        */
+       struct mutex ras_tbl_mutex;
 };
 
 /*
@@ -74,21 +105,26 @@ struct eeprom_table_record {
 
        unsigned char mem_channel;
        unsigned char mcumc_id;
-}__attribute__((__packed__));
+} __packed;
 
 int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
-                       bool *exceed_err_limit);
+                          bool *exceed_err_limit);
+
 int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control);
 
 bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev);
 
-int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
-                                           struct eeprom_table_record *records,
-                                           bool write,
-                                           int num);
+int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control,
+                          struct eeprom_table_record *records, const u32 num);
+
+int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control,
+                            struct eeprom_table_record *records, const u32 num);
+
+inline uint32_t amdgpu_ras_eeprom_max_record_count(void);
 
-inline uint32_t amdgpu_ras_eeprom_get_record_max_length(void);
+void amdgpu_ras_debugfs_set_ret_size(struct amdgpu_ras_eeprom_control *control);
 
-void amdgpu_ras_eeprom_test(struct amdgpu_ras_eeprom_control *control);
+extern const struct file_operations amdgpu_ras_debugfs_eeprom_size_ops;
+extern const struct file_operations amdgpu_ras_debugfs_eeprom_table_ops;
 
 #endif // _AMDGPU_RAS_EEPROM_H
index e7d3d0dbdd967c731d850ca0946bbb00ccbc9368..27adffa7658d613875810d6f85e94787c6f47f4c 100644 (file)
@@ -107,8 +107,6 @@ struct amdgpu_fence_driver {
 };
 
 int amdgpu_fence_driver_init(struct amdgpu_device *adev);
-void amdgpu_fence_driver_fini_hw(struct amdgpu_device *adev);
-void amdgpu_fence_driver_fini_sw(struct amdgpu_device *adev);
 void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring);
 
 int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
@@ -117,8 +115,9 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
 int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
                                   struct amdgpu_irq_src *irq_src,
                                   unsigned irq_type);
-void amdgpu_fence_driver_suspend(struct amdgpu_device *adev);
-void amdgpu_fence_driver_resume(struct amdgpu_device *adev);
+void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev);
+void amdgpu_fence_driver_sw_fini(struct amdgpu_device *adev);
+void amdgpu_fence_driver_hw_init(struct amdgpu_device *adev);
 int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **fence,
                      unsigned flags);
 int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s,
index 7a4775ab680484c7e975cfc1af33383e47ca0f1f..00afd0dcae86cd7a24db1ec50c6087a5273afb12 100644 (file)
@@ -127,8 +127,8 @@ struct amdgpu_rlc_funcs {
        void (*reset)(struct amdgpu_device *adev);
        void (*start)(struct amdgpu_device *adev);
        void (*update_spm_vmid)(struct amdgpu_device *adev, unsigned vmid);
-       void (*rlcg_wreg)(struct amdgpu_device *adev, u32 offset, u32 v, u32 acc_flags, u32 hwip);
-       u32 (*rlcg_rreg)(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip);
+       void (*sriov_wreg)(struct amdgpu_device *adev, u32 offset, u32 v, u32 acc_flags, u32 hwip);
+       u32 (*sriov_rreg)(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip);
        bool (*is_rlcg_access_range)(struct amdgpu_device *adev, uint32_t reg);
 };
 
index acd95d3a44343f055370b2e97ca8112521babb98..9fd5db58067d5f45b3908524acbd663014eff54d 100644 (file)
@@ -1396,6 +1396,41 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
        return ttm_bo_eviction_valuable(bo, place);
 }
 
+static void amdgpu_ttm_vram_mm_access(struct amdgpu_device *adev, loff_t pos,
+                                     void *buf, size_t size, bool write)
+{
+       while (size) {
+               uint64_t aligned_pos = ALIGN_DOWN(pos, 4);
+               uint64_t bytes = 4 - (pos & 0x3);
+               uint32_t shift = (pos & 0x3) * 8;
+               uint32_t mask = 0xffffffff << shift;
+               uint32_t value = 0;
+
+               if (size < bytes) {
+                       mask &= 0xffffffff >> (bytes - size) * 8;
+                       bytes = size;
+               }
+
+               if (mask != 0xffffffff) {
+                       amdgpu_device_mm_access(adev, aligned_pos, &value, 4, false);
+                       if (write) {
+                               value &= ~mask;
+                               value |= (*(uint32_t *)buf << shift) & mask;
+                               amdgpu_device_mm_access(adev, aligned_pos, &value, 4, true);
+                       } else {
+                               value = (value & mask) >> shift;
+                               memcpy(buf, &value, bytes);
+                       }
+               } else {
+                       amdgpu_device_mm_access(adev, aligned_pos, buf, 4, write);
+               }
+
+               pos += bytes;
+               buf += bytes;
+               size -= bytes;
+       }
+}
+
 /**
  * amdgpu_ttm_access_memory - Read or Write memory that backs a buffer object.
  *
@@ -1415,8 +1450,6 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo,
        struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
        struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev);
        struct amdgpu_res_cursor cursor;
-       unsigned long flags;
-       uint32_t value = 0;
        int ret = 0;
 
        if (bo->resource->mem_type != TTM_PL_VRAM)
@@ -1424,41 +1457,21 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo,
 
        amdgpu_res_first(bo->resource, offset, len, &cursor);
        while (cursor.remaining) {
-               uint64_t aligned_pos = cursor.start & ~(uint64_t)3;
-               uint64_t bytes = 4 - (cursor.start & 3);
-               uint32_t shift = (cursor.start & 3) * 8;
-               uint32_t mask = 0xffffffff << shift;
-
-               if (cursor.size < bytes) {
-                       mask &= 0xffffffff >> (bytes - cursor.size) * 8;
-                       bytes = cursor.size;
+               size_t count, size = cursor.size;
+               loff_t pos = cursor.start;
+
+               count = amdgpu_device_aper_access(adev, pos, buf, size, write);
+               size -= count;
+               if (size) {
+                       /* using MM to access rest vram and handle un-aligned address */
+                       pos += count;
+                       buf += count;
+                       amdgpu_ttm_vram_mm_access(adev, pos, buf, size, write);
                }
 
-               if (mask != 0xffffffff) {
-                       spin_lock_irqsave(&adev->mmio_idx_lock, flags);
-                       WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)aligned_pos) | 0x80000000);
-                       WREG32_NO_KIQ(mmMM_INDEX_HI, aligned_pos >> 31);
-                       value = RREG32_NO_KIQ(mmMM_DATA);
-                       if (write) {
-                               value &= ~mask;
-                               value |= (*(uint32_t *)buf << shift) & mask;
-                               WREG32_NO_KIQ(mmMM_DATA, value);
-                       }
-                       spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
-                       if (!write) {
-                               value = (value & mask) >> shift;
-                               memcpy(buf, &value, bytes);
-                       }
-               } else {
-                       bytes = cursor.size & ~0x3ULL;
-                       amdgpu_device_vram_access(adev, cursor.start,
-                                                 (uint32_t *)buf, bytes,
-                                                 write);
-               }
-
-               ret += bytes;
-               buf = (uint8_t *)buf + bytes;
-               amdgpu_res_next(&cursor, bytes);
+               ret += cursor.size;
+               buf += cursor.size;
+               amdgpu_res_next(&cursor, cursor.size);
        }
 
        return ret;
@@ -2148,7 +2161,6 @@ static ssize_t amdgpu_ttm_vram_write(struct file *f, const char __user *buf,
                return -ENXIO;
 
        while (size) {
-               unsigned long flags;
                uint32_t value;
 
                if (*pos >= adev->gmc.mc_vram_size)
@@ -2158,11 +2170,7 @@ static ssize_t amdgpu_ttm_vram_write(struct file *f, const char __user *buf,
                if (r)
                        return r;
 
-               spin_lock_irqsave(&adev->mmio_idx_lock, flags);
-               WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)*pos) | 0x80000000);
-               WREG32_NO_KIQ(mmMM_INDEX_HI, *pos >> 31);
-               WREG32_NO_KIQ(mmMM_DATA, value);
-               spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
+               amdgpu_device_mm_access(adev, *pos, &value, 4, true);
 
                result += 4;
                buf += 4;
index 2834981f8c0813b183647fd78d2a3cbc568dc516..5fdeceaa979f91fd1d1bf8dc661c439a35fc1207 100644 (file)
@@ -409,6 +409,12 @@ amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type)
                        return AMDGPU_FW_LOAD_DIRECT;
                else
                        return AMDGPU_FW_LOAD_PSP;
+       case CHIP_CYAN_SKILLFISH:
+               if (!(load_type &&
+                     adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2))
+                       return AMDGPU_FW_LOAD_DIRECT;
+               else
+                       return AMDGPU_FW_LOAD_PSP;
        default:
                DRM_ERROR("Unknown firmware load type\n");
        }
@@ -416,6 +422,84 @@ amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type)
        return AMDGPU_FW_LOAD_DIRECT;
 }
 
+const char *amdgpu_ucode_name(enum AMDGPU_UCODE_ID ucode_id)
+{
+       switch (ucode_id) {
+       case AMDGPU_UCODE_ID_SDMA0:
+               return "SDMA0";
+       case AMDGPU_UCODE_ID_SDMA1:
+               return "SDMA1";
+       case AMDGPU_UCODE_ID_SDMA2:
+               return "SDMA2";
+       case AMDGPU_UCODE_ID_SDMA3:
+               return "SDMA3";
+       case AMDGPU_UCODE_ID_SDMA4:
+               return "SDMA4";
+       case AMDGPU_UCODE_ID_SDMA5:
+               return "SDMA5";
+       case AMDGPU_UCODE_ID_SDMA6:
+               return "SDMA6";
+       case AMDGPU_UCODE_ID_SDMA7:
+               return "SDMA7";
+       case AMDGPU_UCODE_ID_CP_CE:
+               return "CP_CE";
+       case AMDGPU_UCODE_ID_CP_PFP:
+               return "CP_PFP";
+       case AMDGPU_UCODE_ID_CP_ME:
+               return "CP_ME";
+       case AMDGPU_UCODE_ID_CP_MEC1:
+               return "CP_MEC1";
+       case AMDGPU_UCODE_ID_CP_MEC1_JT:
+               return "CP_MEC1_JT";
+       case AMDGPU_UCODE_ID_CP_MEC2:
+               return "CP_MEC2";
+       case AMDGPU_UCODE_ID_CP_MEC2_JT:
+               return "CP_MEC2_JT";
+       case AMDGPU_UCODE_ID_CP_MES:
+               return "CP_MES";
+       case AMDGPU_UCODE_ID_CP_MES_DATA:
+               return "CP_MES_DATA";
+       case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL:
+               return "RLC_RESTORE_LIST_CNTL";
+       case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM:
+               return "RLC_RESTORE_LIST_GPM_MEM";
+       case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM:
+               return "RLC_RESTORE_LIST_SRM_MEM";
+       case AMDGPU_UCODE_ID_RLC_IRAM:
+               return "RLC_IRAM";
+       case AMDGPU_UCODE_ID_RLC_DRAM:
+               return "RLC_DRAM";
+       case AMDGPU_UCODE_ID_RLC_G:
+               return "RLC_G";
+       case AMDGPU_UCODE_ID_STORAGE:
+               return "STORAGE";
+       case AMDGPU_UCODE_ID_SMC:
+               return "SMC";
+       case AMDGPU_UCODE_ID_UVD:
+               return "UVD";
+       case AMDGPU_UCODE_ID_UVD1:
+               return "UVD1";
+       case AMDGPU_UCODE_ID_VCE:
+               return "VCE";
+       case AMDGPU_UCODE_ID_VCN:
+               return "VCN";
+       case AMDGPU_UCODE_ID_VCN1:
+               return "VCN1";
+       case AMDGPU_UCODE_ID_DMCU_ERAM:
+               return "DMCU_ERAM";
+       case AMDGPU_UCODE_ID_DMCU_INTV:
+               return "DMCU_INTV";
+       case AMDGPU_UCODE_ID_VCN0_RAM:
+               return "VCN0_RAM";
+       case AMDGPU_UCODE_ID_VCN1_RAM:
+               return "VCN1_RAM";
+       case AMDGPU_UCODE_ID_DMCUB:
+               return "DMCUB";
+       default:
+               return "UNKNOWN UCODE";
+       }
+}
+
 #define FW_VERSION_ATTR(name, mode, field)                             \
 static ssize_t show_##name(struct device *dev,                         \
                          struct device_attribute *attr,                \
@@ -440,7 +524,7 @@ FW_VERSION_ATTR(rlc_srlg_fw_version, 0444, gfx.rlc_srlg_fw_version);
 FW_VERSION_ATTR(rlc_srls_fw_version, 0444, gfx.rlc_srls_fw_version);
 FW_VERSION_ATTR(mec_fw_version, 0444, gfx.mec_fw_version);
 FW_VERSION_ATTR(mec2_fw_version, 0444, gfx.mec2_fw_version);
-FW_VERSION_ATTR(sos_fw_version, 0444, psp.sos_fw_version);
+FW_VERSION_ATTR(sos_fw_version, 0444, psp.sos.fw_version);
 FW_VERSION_ATTR(asd_fw_version, 0444, psp.asd_fw_version);
 FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ta_ras_ucode_version);
 FW_VERSION_ATTR(ta_xgmi_fw_version, 0444, psp.ta_xgmi_ucode_version);
index 270309e7f5f59a06c23dad57227c21aaa237a6bc..e2e2624ac653bfbc8985ac9daff41616f66edaf5 100644 (file)
@@ -71,7 +71,7 @@ struct smc_firmware_header_v2_1 {
         uint32_t pptable_entry_offset;
 };
 
-struct psp_fw_bin_desc {
+struct psp_fw_legacy_bin_desc {
        uint32_t fw_version;
        uint32_t offset_bytes;
        uint32_t size_bytes;
@@ -80,30 +80,57 @@ struct psp_fw_bin_desc {
 /* version_major=1, version_minor=0 */
 struct psp_firmware_header_v1_0 {
        struct common_firmware_header header;
-       struct psp_fw_bin_desc sos;
+       struct psp_fw_legacy_bin_desc sos;
 };
 
 /* version_major=1, version_minor=1 */
 struct psp_firmware_header_v1_1 {
        struct psp_firmware_header_v1_0 v1_0;
-       struct psp_fw_bin_desc toc;
-       struct psp_fw_bin_desc kdb;
+       struct psp_fw_legacy_bin_desc toc;
+       struct psp_fw_legacy_bin_desc kdb;
 };
 
 /* version_major=1, version_minor=2 */
 struct psp_firmware_header_v1_2 {
        struct psp_firmware_header_v1_0 v1_0;
-       struct psp_fw_bin_desc res;
-       struct psp_fw_bin_desc kdb;
+       struct psp_fw_legacy_bin_desc res;
+       struct psp_fw_legacy_bin_desc kdb;
 };
 
 /* version_major=1, version_minor=3 */
 struct psp_firmware_header_v1_3 {
        struct psp_firmware_header_v1_1 v1_1;
-       struct psp_fw_bin_desc spl;
-       struct psp_fw_bin_desc rl;
-       struct psp_fw_bin_desc sys_drv_aux;
-       struct psp_fw_bin_desc sos_aux;
+       struct psp_fw_legacy_bin_desc spl;
+       struct psp_fw_legacy_bin_desc rl;
+       struct psp_fw_legacy_bin_desc sys_drv_aux;
+       struct psp_fw_legacy_bin_desc sos_aux;
+};
+
+struct psp_fw_bin_desc {
+       uint32_t fw_type;
+       uint32_t fw_version;
+       uint32_t offset_bytes;
+       uint32_t size_bytes;
+};
+
+enum psp_fw_type {
+       PSP_FW_TYPE_UNKOWN,
+       PSP_FW_TYPE_PSP_SOS,
+       PSP_FW_TYPE_PSP_SYS_DRV,
+       PSP_FW_TYPE_PSP_KDB,
+       PSP_FW_TYPE_PSP_TOC,
+       PSP_FW_TYPE_PSP_SPL,
+       PSP_FW_TYPE_PSP_RL,
+       PSP_FW_TYPE_PSP_SOC_DRV,
+       PSP_FW_TYPE_PSP_INTF_DRV,
+       PSP_FW_TYPE_PSP_DBG_DRV,
+};
+
+/* version_major=2, version_minor=0 */
+struct psp_firmware_header_v2_0 {
+       struct common_firmware_header header;
+       uint32_t psp_fw_bin_count;
+       struct psp_fw_bin_desc psp_fw_bin[];
 };
 
 /* version_major=1, version_minor=0 */
@@ -138,18 +165,11 @@ enum ta_fw_type {
        TA_FW_TYPE_MAX_INDEX,
 };
 
-struct ta_fw_bin_desc {
-       uint32_t fw_type;
-       uint32_t fw_version;
-       uint32_t offset_bytes;
-       uint32_t size_bytes;
-};
-
 /* version_major=2, version_minor=0 */
 struct ta_firmware_header_v2_0 {
        struct common_firmware_header header;
        uint32_t ta_fw_bin_count;
-       struct ta_fw_bin_desc ta_fw_bin[];
+       struct psp_fw_bin_desc ta_fw_bin[];
 };
 
 /* version_major=1, version_minor=0 */
@@ -312,6 +332,7 @@ union amdgpu_firmware_header {
        struct psp_firmware_header_v1_0 psp;
        struct psp_firmware_header_v1_1 psp_v1_1;
        struct psp_firmware_header_v1_3 psp_v1_3;
+       struct psp_firmware_header_v2_0 psp_v2_0;
        struct ta_firmware_header_v1_0 ta;
        struct ta_firmware_header_v2_0 ta_v2_0;
        struct gfx_firmware_header_v1_0 gfx;
@@ -326,7 +347,7 @@ union amdgpu_firmware_header {
        uint8_t raw[0x100];
 };
 
-#define UCODE_MAX_TA_PACKAGING ((sizeof(union amdgpu_firmware_header) - sizeof(struct common_firmware_header) - 4) / sizeof(struct ta_fw_bin_desc))
+#define UCODE_MAX_PSP_PACKAGING ((sizeof(union amdgpu_firmware_header) - sizeof(struct common_firmware_header) - 4) / sizeof(struct psp_fw_bin_desc))
 
 /*
  * fw loading support
@@ -449,4 +470,6 @@ void amdgpu_ucode_sysfs_fini(struct amdgpu_device *adev);
 enum amdgpu_firmware_load_type
 amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type);
 
+const char *amdgpu_ucode_name(enum AMDGPU_UCODE_ID ucode_id);
+
 #endif
index f4489773715e654edbed66ba19ec3e9b35783764..0c7c56a91b251dbb21f2269193bb7c5ab45a7283 100644 (file)
@@ -134,7 +134,7 @@ int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev,
                        amdgpu_ras_save_bad_pages(adev);
 
                        if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->send_hbm_bad_pages_num)
-                               adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.num_recs);
+                               adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.ras_num_recs);
                }
 
                amdgpu_ras_reset_gpu(adev);
index b71dd1deeb2d374c2ebed5e049e01746c33988ff..12a7cc2f01cd3d9bbc1b308b4c46a993bd9e81fd 100644 (file)
@@ -531,7 +531,7 @@ static void amdgpu_virt_populate_vf2pf_ucode_info(struct amdgpu_device *adev)
        POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_RLC_SRLS, adev->gfx.rlc_srls_fw_version);
        POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC,      adev->gfx.mec_fw_version);
        POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC2,     adev->gfx.mec2_fw_version);
-       POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SOS,      adev->psp.sos_fw_version);
+       POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SOS,      adev->psp.sos.fw_version);
        POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD,      adev->psp.asd_fw_version);
        POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_RAS,   adev->psp.ta_ras_ucode_version);
        POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_XGMI,  adev->psp.ta_xgmi_ucode_version);
index 078c068937feeebe698e33f720c26ab8ec1d0ba3..6362e861a3f527eab63327491d8077beb8bb3047 100644 (file)
@@ -88,6 +88,46 @@ struct amdgpu_prt_cb {
        struct dma_fence_cb cb;
 };
 
+/**
+ * amdgpu_vm_set_pasid - manage pasid and vm ptr mapping
+ *
+ * @adev: amdgpu_device pointer
+ * @vm: amdgpu_vm pointer
+ * @pasid: the pasid the VM is using on this GPU
+ *
+ * Set the pasid this VM is using on this GPU, can also be used to remove the
+ * pasid by passing in zero.
+ *
+ */
+int amdgpu_vm_set_pasid(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+                       u32 pasid)
+{
+       int r;
+
+       if (vm->pasid == pasid)
+               return 0;
+
+       if (vm->pasid) {
+               r = xa_err(xa_erase_irq(&adev->vm_manager.pasids, vm->pasid));
+               if (r < 0)
+                       return r;
+
+               vm->pasid = 0;
+       }
+
+       if (pasid) {
+               r = xa_err(xa_store_irq(&adev->vm_manager.pasids, pasid, vm,
+                                       GFP_KERNEL));
+               if (r < 0)
+                       return r;
+
+               vm->pasid = pasid;
+       }
+
+
+       return 0;
+}
+
 /*
  * vm eviction_lock can be taken in MMU notifiers. Make sure no reclaim-FS
  * happens while holding this lock anywhere to prevent deadlocks when
@@ -2863,14 +2903,13 @@ long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout)
  *
  * @adev: amdgpu_device pointer
  * @vm: requested vm
- * @pasid: Process address space identifier
  *
  * Init @vm fields.
  *
  * Returns:
  * 0 for success, error for failure.
  */
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid)
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
 {
        struct amdgpu_bo *root_bo;
        struct amdgpu_bo_vm *root;
@@ -2944,19 +2983,6 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid)
 
        amdgpu_bo_unreserve(vm->root.bo);
 
-       if (pasid) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
-               r = idr_alloc(&adev->vm_manager.pasid_idr, vm, pasid, pasid + 1,
-                             GFP_ATOMIC);
-               spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
-               if (r < 0)
-                       goto error_free_root;
-
-               vm->pasid = pasid;
-       }
-
        INIT_KFIFO(vm->faults);
 
        return 0;
@@ -3012,7 +3038,6 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev,
  *
  * @adev: amdgpu_device pointer
  * @vm: requested vm
- * @pasid: pasid to use
  *
  * This only works on GFX VMs that don't have any BOs added and no
  * page tables allocated yet.
@@ -3020,7 +3045,6 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev,
  * Changes the following VM parameters:
  * - use_cpu_for_update
  * - pte_supports_ats
- * - pasid (old PASID is released, because compute manages its own PASIDs)
  *
  * Reinitializes the page directory to reflect the changed ATS
  * setting.
@@ -3028,8 +3052,7 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev,
  * Returns:
  * 0 for success, -errno for errors.
  */
-int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,
-                          u32 pasid)
+int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)
 {
        bool pte_support_ats = (adev->asic_type == CHIP_RAVEN);
        int r;
@@ -3043,19 +3066,6 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,
        if (r)
                goto unreserve_bo;
 
-       if (pasid) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
-               r = idr_alloc(&adev->vm_manager.pasid_idr, vm, pasid, pasid + 1,
-                             GFP_ATOMIC);
-               spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
-
-               if (r == -ENOSPC)
-                       goto unreserve_bo;
-               r = 0;
-       }
-
        /* Check if PD needs to be reinitialized and do it before
         * changing any other state, in case it fails.
         */
@@ -3065,7 +3075,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,
                                       to_amdgpu_bo_vm(vm->root.bo),
                                       false);
                if (r)
-                       goto free_idr;
+                       goto unreserve_bo;
        }
 
        /* Update VM state */
@@ -3082,7 +3092,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,
                r = amdgpu_bo_sync_wait(vm->root.bo,
                                        AMDGPU_FENCE_OWNER_UNDEFINED, true);
                if (r)
-                       goto free_idr;
+                       goto unreserve_bo;
 
                vm->update_funcs = &amdgpu_vm_cpu_funcs;
        } else {
@@ -3092,36 +3102,11 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,
        vm->last_update = NULL;
        vm->is_compute_context = true;
 
-       if (vm->pasid) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
-               idr_remove(&adev->vm_manager.pasid_idr, vm->pasid);
-               spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
-
-               /* Free the original amdgpu allocated pasid
-                * Will be replaced with kfd allocated pasid
-                */
-               amdgpu_pasid_free(vm->pasid);
-               vm->pasid = 0;
-       }
-
        /* Free the shadow bo for compute VM */
        amdgpu_bo_unref(&to_amdgpu_bo_vm(vm->root.bo)->shadow);
 
-       if (pasid)
-               vm->pasid = pasid;
-
        goto unreserve_bo;
 
-free_idr:
-       if (pasid) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
-               idr_remove(&adev->vm_manager.pasid_idr, pasid);
-               spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
-       }
 unreserve_bo:
        amdgpu_bo_unreserve(vm->root.bo);
        return r;
@@ -3137,14 +3122,7 @@ unreserve_bo:
  */
 void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)
 {
-       if (vm->pasid) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
-               idr_remove(&adev->vm_manager.pasid_idr, vm->pasid);
-               spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
-       }
-       vm->pasid = 0;
+       amdgpu_vm_set_pasid(adev, vm, 0);
        vm->is_compute_context = false;
 }
 
@@ -3168,15 +3146,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
 
        root = amdgpu_bo_ref(vm->root.bo);
        amdgpu_bo_reserve(root, true);
-       if (vm->pasid) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
-               idr_remove(&adev->vm_manager.pasid_idr, vm->pasid);
-               spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
-               vm->pasid = 0;
-       }
-
+       amdgpu_vm_set_pasid(adev, vm, 0);
        dma_fence_wait(vm->last_unlocked, false);
        dma_fence_put(vm->last_unlocked);
 
@@ -3258,8 +3228,7 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)
        adev->vm_manager.vm_update_mode = 0;
 #endif
 
-       idr_init(&adev->vm_manager.pasid_idr);
-       spin_lock_init(&adev->vm_manager.pasid_lock);
+       xa_init_flags(&adev->vm_manager.pasids, XA_FLAGS_LOCK_IRQ);
 }
 
 /**
@@ -3271,8 +3240,8 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)
  */
 void amdgpu_vm_manager_fini(struct amdgpu_device *adev)
 {
-       WARN_ON(!idr_is_empty(&adev->vm_manager.pasid_idr));
-       idr_destroy(&adev->vm_manager.pasid_idr);
+       WARN_ON(!xa_empty(&adev->vm_manager.pasids));
+       xa_destroy(&adev->vm_manager.pasids);
 
        amdgpu_vmid_mgr_fini(adev);
 }
@@ -3341,13 +3310,13 @@ void amdgpu_vm_get_task_info(struct amdgpu_device *adev, u32 pasid,
        struct amdgpu_vm *vm;
        unsigned long flags;
 
-       spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
+       xa_lock_irqsave(&adev->vm_manager.pasids, flags);
 
-       vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
+       vm = xa_load(&adev->vm_manager.pasids, pasid);
        if (vm)
                *task_info = vm->task_info;
 
-       spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
+       xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
 }
 
 /**
@@ -3389,15 +3358,15 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
        struct amdgpu_vm *vm;
        int r;
 
-       spin_lock_irqsave(&adev->vm_manager.pasid_lock, irqflags);
-       vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
+       xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
+       vm = xa_load(&adev->vm_manager.pasids, pasid);
        if (vm) {
                root = amdgpu_bo_ref(vm->root.bo);
                is_compute_context = vm->is_compute_context;
        } else {
                root = NULL;
        }
-       spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, irqflags);
+       xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
 
        if (!root)
                return false;
@@ -3415,11 +3384,11 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
                goto error_unref;
 
        /* Double check that the VM still exists */
-       spin_lock_irqsave(&adev->vm_manager.pasid_lock, irqflags);
-       vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
+       xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
+       vm = xa_load(&adev->vm_manager.pasids, pasid);
        if (vm && vm->root.bo != root)
                vm = NULL;
-       spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, irqflags);
+       xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
        if (!vm)
                goto error_unlock;
 
index f8fa653d4da747c58dcfdd0307269656f2c31f1f..ee0028ec2c4f8149f62584f0425aefe625aef0c2 100644 (file)
@@ -359,8 +359,7 @@ struct amdgpu_vm_manager {
        /* PASID to VM mapping, will be used in interrupt context to
         * look up VM of a page fault
         */
-       struct idr                              pasid_idr;
-       spinlock_t                              pasid_lock;
+       struct xarray                           pasids;
 };
 
 struct amdgpu_bo_va_mapping;
@@ -375,9 +374,12 @@ extern const struct amdgpu_vm_update_funcs amdgpu_vm_sdma_funcs;
 void amdgpu_vm_manager_init(struct amdgpu_device *adev);
 void amdgpu_vm_manager_fini(struct amdgpu_device *adev);
 
+int amdgpu_vm_set_pasid(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+                       u32 pasid);
+
 long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout);
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid);
-int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid);
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm);
+int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm);
 void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm);
 void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
 void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
index 8567d5d773460b66a410cc660dbad38f12bf391d..258cf86b32f6e29fddc42b4b02dde0b458e37ed9 100644 (file)
@@ -486,6 +486,18 @@ int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev,
        return  -EINVAL;
 }
 
+int amdgpu_xgmi_get_num_links(struct amdgpu_device *adev,
+               struct amdgpu_device *peer_adev)
+{
+       struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info;
+       int i;
+
+       for (i = 0 ; i < top->num_nodes; ++i)
+               if (top->nodes[i].node_id == peer_adev->gmc.xgmi.node_id)
+                       return top->nodes[i].num_links;
+       return  -EINVAL;
+}
+
 int amdgpu_xgmi_add_device(struct amdgpu_device *adev)
 {
        struct psp_xgmi_topology_info *top_info;
index 12969c0830d5ce9d8194bd4974e563864d22ad1f..d2189bf7d428ef7781a3c2b02a2a4e22b0d4963c 100644 (file)
@@ -59,6 +59,8 @@ int amdgpu_xgmi_remove_device(struct amdgpu_device *adev);
 int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate);
 int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev,
                struct amdgpu_device *peer_adev);
+int amdgpu_xgmi_get_num_links(struct amdgpu_device *adev,
+               struct amdgpu_device *peer_adev);
 uint64_t amdgpu_xgmi_get_relative_phy_addr(struct amdgpu_device *adev,
                                           uint64_t addr);
 static inline bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/cyan_skillfish_reg_init.c b/drivers/gpu/drm/amd/amdgpu/cyan_skillfish_reg_init.c
new file mode 100644 (file)
index 0000000..5880881
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2018 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "amdgpu.h"
+#include "nv.h"
+
+#include "soc15_common.h"
+#include "soc15_hw_ip.h"
+#include "cyan_skillfish_ip_offset.h"
+
+int cyan_skillfish_reg_base_init(struct amdgpu_device *adev)
+{
+       /* HW has more IP blocks,  only initialized the blocke needed by driver */
+       uint32_t i;
+       for (i = 0 ; i < MAX_INSTANCE ; ++i) {
+               adev->reg_offset[GC_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
+               adev->reg_offset[HDP_HWIP][i] = (uint32_t *)(&(HDP_BASE.instance[i]));
+               adev->reg_offset[MMHUB_HWIP][i] = (uint32_t *)(&(MMHUB_BASE.instance[i]));
+               adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i]));
+               adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i]));
+               adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i]));
+               adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i]));
+               adev->reg_offset[VCN_HWIP][i] = (uint32_t *)(&(UVD0_BASE.instance[i]));
+               adev->reg_offset[DF_HWIP][i] = (uint32_t *)(&(DF_BASE.instance[i]));
+               adev->reg_offset[DCE_HWIP][i] = (uint32_t *)(&(DMU_BASE.instance[i]));
+               adev->reg_offset[OSSSYS_HWIP][i] = (uint32_t *)(&(OSSSYS_BASE.instance[i]));
+               adev->reg_offset[SDMA0_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
+               adev->reg_offset[SDMA1_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
+               adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
+       }
+       return 0;
+}
index a64b2c706090ea6abe0d38c2cf6d00e7e66a7fd9..24b0195fe6650970f09568c86c28764ed0ec47be 100644 (file)
 #define GFX10_NUM_GFX_RINGS_Sienna_Cichlid     1
 #define GFX10_MEC_HPD_SIZE     2048
 
+#define RLCG_VFGATE_DISABLED   0x4000000
+#define RLCG_WRONG_OPERATION_TYPE      0x2000000
+#define RLCG_NOT_IN_RANGE      0x1000000
+
 #define F32_CE_PROGRAM_RAM_SIZE                65536
 #define RLCG_UCODE_LOADING_START_ADDRESS       0x00002000L
 
 #define GFX_RLCG_GC_READ       (0x1 << 28)
 #define GFX_RLCG_MMHUB_WRITE   (0x2 << 28)
 
+#define RLCG_ERROR_REPORT_ENABLED(adev) \
+       (amdgpu_sriov_reg_indirect_mmhub(adev) || amdgpu_sriov_reg_indirect_gc(adev))
+
 MODULE_FIRMWARE("amdgpu/navi10_ce.bin");
 MODULE_FIRMWARE("amdgpu/navi10_pfp.bin");
 MODULE_FIRMWARE("amdgpu/navi10_me.bin");
@@ -249,6 +256,39 @@ MODULE_FIRMWARE("amdgpu/yellow_carp_mec.bin");
 MODULE_FIRMWARE("amdgpu/yellow_carp_mec2.bin");
 MODULE_FIRMWARE("amdgpu/yellow_carp_rlc.bin");
 
+MODULE_FIRMWARE("amdgpu/cyan_skillfish_ce.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish_pfp.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish_me.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish_mec.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish_mec2.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish_rlc.bin");
+
+MODULE_FIRMWARE("amdgpu/cyan_skillfish2_ce.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish2_pfp.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish2_me.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish2_mec.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish2_mec2.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish2_rlc.bin");
+
+static const struct soc15_reg_golden golden_settings_gc_10_0[] =
+{
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_INDEX, 0xffffffff, 0x00000000),
+       /* TA_GRAD_ADJ_UCONFIG -> TA_GRAD_ADJ */
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2544c382),
+       /* VGT_TF_RING_SIZE_UMD -> VGT_TF_RING_SIZE */
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2262c24e),
+       /* VGT_HS_OFFCHIP_PARAM_UMD -> VGT_HS_OFFCHIP_PARAM */
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x226cc24f),
+       /* VGT_TF_MEMORY_BASE_UMD -> VGT_TF_MEMORY_BASE */
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x226ec250),
+       /* VGT_TF_MEMORY_BASE_HI_UMD -> VGT_TF_MEMORY_BASE_HI */
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2278c261),
+       /* VGT_ESGS_RING_SIZE_UMD -> VGT_ESGS_RING_SIZE */
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2232c240),
+       /* VGT_GSVS_RING_SIZE_UMD -> VGT_GSVS_RING_SIZE */
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2233c241),
+};
+
 static const struct soc15_reg_golden golden_settings_gc_10_1[] =
 {
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_4, 0xffffffff, 0x00400014),
@@ -1486,6 +1526,7 @@ static u32 gfx_v10_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32
        uint32_t i = 0;
        uint32_t retries = 50000;
        u32 ret = 0;
+       u32 tmp;
 
        scratch_reg0 = adev->rmmio +
                       (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG0_BASE_IDX] + mmSCRATCH_REG0) * 4;
@@ -1519,9 +1560,8 @@ static u32 gfx_v10_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32
                writel(v, scratch_reg0);
                writel(offset | flag, scratch_reg1);
                writel(1, spare_int);
-               for (i = 0; i < retries; i++) {
-                       u32 tmp;
 
+               for (i = 0; i < retries; i++) {
                        tmp = readl(scratch_reg1);
                        if (!(tmp & flag))
                                break;
@@ -1529,8 +1569,19 @@ static u32 gfx_v10_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32
                        udelay(10);
                }
 
-               if (i >= retries)
-                       pr_err("timeout: rlcg program reg:0x%05x failed !\n", offset);
+               if (i >= retries) {
+                       if (RLCG_ERROR_REPORT_ENABLED(adev)) {
+                               if (tmp & RLCG_VFGATE_DISABLED)
+                                       pr_err("The vfgate is disabled, program reg:0x%05x failed!\n", offset);
+                               else if (tmp & RLCG_WRONG_OPERATION_TYPE)
+                                       pr_err("Wrong operation type, program reg:0x%05x failed!\n", offset);
+                               else if (tmp & RLCG_NOT_IN_RANGE)
+                                       pr_err("The register is not in range, program reg:0x%05x failed!\n", offset);
+                               else
+                                       pr_err("Unknown error type, program reg:0x%05x failed!\n", offset);
+                       } else
+                               pr_err("timeout: rlcg program reg:0x%05x failed!\n", offset);
+               }
        }
 
        ret = readl(scratch_reg0);
@@ -1538,7 +1589,7 @@ static u32 gfx_v10_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32
        return ret;
 }
 
-static void gfx_v10_rlcg_wreg(struct amdgpu_device *adev, u32 offset, u32 value, u32 acc_flags, u32 hwip)
+static void gfx_v10_sriov_wreg(struct amdgpu_device *adev, u32 offset, u32 value, u32 acc_flags, u32 hwip)
 {
        u32 rlcg_flag;
 
@@ -1554,7 +1605,7 @@ static void gfx_v10_rlcg_wreg(struct amdgpu_device *adev, u32 offset, u32 value,
                WREG32(offset, value);
 }
 
-static u32 gfx_v10_rlcg_rreg(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip)
+static u32 gfx_v10_sriov_rreg(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip)
 {
        u32 rlcg_flag;
 
@@ -3488,12 +3539,51 @@ static const struct soc15_reg_golden golden_settings_gc_10_3_5[] = {
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffbfffff, 0x00a00000)
 };
 
+static const struct soc15_reg_golden golden_settings_gc_10_0_cyan_skillfish[] = {
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGE_FAST_CLKS, 0x3fffffff, 0x0000493e),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_CPF_CLK_CTRL, 0xfcff8fff, 0xf8000100),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_CLK_CTRL, 0xff7f0fff, 0x3c000100),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_3, 0xa0000000, 0xa0000000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_4, 0x00008000, 0x003c8014),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCH_DRAM_BURST_CTRL, 0x00000010, 0x00000017),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCH_PIPE_STEER, 0xffffffff, 0xd8d8d8d8),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCH_VC5_ENABLE, 0x00000003, 0x00000003),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_SD_CNTL, 0x800007ff, 0x000005ff),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG, 0xffffffff, 0x20000000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG3, 0xffffffff, 0x00000200),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG4, 0xffffffff, 0x04800000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_LAST_OF_BURST_CONFIG, 0xffffffff, 0x03860210),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGB_ADDR_CONFIG, 0x0c1800ff, 0x00000044),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCR_GENERAL_CNTL, 0x00009d00, 0x00008500),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCMC_VM_CACHEABLE_DRAM_ADDRESS_END, 0xffffffff, 0x000fffff),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL1_DRAM_BURST_CTRL, 0x00000010, 0x00000017),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL1_PIPE_STEER, 0xfcfcfcfc, 0xd8d8d8d8),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2_PIPE_STEER_0, 0x77707770, 0x21302130),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2_PIPE_STEER_1, 0x77707770, 0x21302130),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2A_ADDR_MATCH_MASK, 0xffffffff, 0xffffffcf),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_ADDR_MATCH_MASK, 0xffffffff, 0xffffffcf),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CGTT_SCLK_CTRL, 0x10000000, 0x10000100),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL2, 0xfc02002f, 0x9402002f),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL3, 0x00002188, 0x00000188),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE, 0x08000009, 0x08000009),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_BINNER_EVENT_CNTL_0, 0xcc3fcc03, 0x842a4c02),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_LINE_STIPPLE_STATE, 0x0000000f, 0x00000000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_SPARE, 0xffff3109, 0xffff3101),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ARB_CONFIG, 0x00000100, 0x00000130),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_LDS_CLK_CTRL, 0xffffffff, 0xffffffff),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmTA_CNTL_AUX, 0x00030008, 0x01030000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0x00800000, 0x00800000)
+};
+
 #define DEFAULT_SH_MEM_CONFIG \
        ((SH_MEM_ADDRESS_MODE_64 << SH_MEM_CONFIG__ADDRESS_MODE__SHIFT) | \
         (SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | \
         (SH_MEM_RETRY_MODE_ALL << SH_MEM_CONFIG__RETRY_MODE__SHIFT) | \
         (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT))
 
+/* TODO: pending on golden setting value of gb address config */
+#define CYAN_SKILLFISH_GB_ADDR_CONFIG_GOLDEN 0x00100044
 
 static void gfx_v10_0_set_ring_funcs(struct amdgpu_device *adev);
 static void gfx_v10_0_set_irq_funcs(struct amdgpu_device *adev);
@@ -3718,6 +3808,14 @@ static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev)
                                                golden_settings_gc_10_3_5,
                                                (const u32)ARRAY_SIZE(golden_settings_gc_10_3_5));
                break;
+       case CHIP_CYAN_SKILLFISH:
+               soc15_program_register_sequence(adev,
+                                               golden_settings_gc_10_0,
+                                               (const u32)ARRAY_SIZE(golden_settings_gc_10_0));
+               soc15_program_register_sequence(adev,
+                                               golden_settings_gc_10_0_cyan_skillfish,
+                                               (const u32)ARRAY_SIZE(golden_settings_gc_10_0_cyan_skillfish));
+               break;
        default:
                break;
        }
@@ -3891,6 +3989,7 @@ static void gfx_v10_0_check_fw_write_wait(struct amdgpu_device *adev)
        case CHIP_NAVI10:
        case CHIP_NAVI12:
        case CHIP_NAVI14:
+       case CHIP_CYAN_SKILLFISH:
                if ((adev->gfx.me_fw_version >= 0x00000046) &&
                    (adev->gfx.me_feature_version >= 27) &&
                    (adev->gfx.pfp_fw_version >= 0x00000068) &&
@@ -4025,6 +4124,12 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
        case CHIP_YELLOW_CARP:
                chip_name = "yellow_carp";
                break;
+       case CHIP_CYAN_SKILLFISH:
+               if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2)
+                       chip_name = "cyan_skillfish2";
+               else
+                       chip_name = "cyan_skillfish";
+               break;
        default:
                BUG();
        }
@@ -4604,6 +4709,14 @@ static void gfx_v10_0_gpu_early_init(struct amdgpu_device *adev)
                adev->gfx.config.gb_addr_config_fields.num_pkrs =
                        1 << REG_GET_FIELD(gb_addr_config, GB_ADDR_CONFIG, NUM_PKRS);
                break;
+       case CHIP_CYAN_SKILLFISH:
+               adev->gfx.config.max_hw_contexts = 8;
+               adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
+               adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
+               adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
+               adev->gfx.config.sc_earlyz_tile_fifo_size = 0x4C0;
+               gb_addr_config = CYAN_SKILLFISH_GB_ADDR_CONFIG_GOLDEN;
+               break;
        default:
                BUG();
                break;
@@ -4708,6 +4821,7 @@ static int gfx_v10_0_sw_init(void *handle)
        case CHIP_NAVI10:
        case CHIP_NAVI14:
        case CHIP_NAVI12:
+       case CHIP_CYAN_SKILLFISH:
                adev->gfx.me.num_me = 1;
                adev->gfx.me.num_pipe_per_me = 1;
                adev->gfx.me.num_queue_per_pipe = 1;
@@ -5319,7 +5433,8 @@ static int gfx_v10_0_rlc_resume(struct amdgpu_device *adev)
 {
        int r;
 
-       if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+       if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
+               adev->psp.autoload_supported) {
 
                r = gfx_v10_0_wait_for_rlc_autoload_complete(adev);
                if (r)
@@ -5379,7 +5494,7 @@ static int gfx_v10_0_parse_rlc_toc(struct amdgpu_device *adev)
        int ret;
        RLC_TABLE_OF_CONTENT *rlc_toc;
 
-       ret = amdgpu_bo_create_reserved(adev, adev->psp.toc_bin_size, PAGE_SIZE,
+       ret = amdgpu_bo_create_reserved(adev, adev->psp.toc.size_bytes, PAGE_SIZE,
                                        AMDGPU_GEM_DOMAIN_GTT,
                                        &adev->gfx.rlc.rlc_toc_bo,
                                        &adev->gfx.rlc.rlc_toc_gpu_addr,
@@ -5390,7 +5505,7 @@ static int gfx_v10_0_parse_rlc_toc(struct amdgpu_device *adev)
        }
 
        /* Copy toc from psp sos fw to rlc toc buffer */
-       memcpy(adev->gfx.rlc.rlc_toc_buf, adev->psp.toc_start_addr, adev->psp.toc_bin_size);
+       memcpy(adev->gfx.rlc.rlc_toc_buf, adev->psp.toc.start_addr, adev->psp.toc.size_bytes);
 
        rlc_toc = (RLC_TABLE_OF_CONTENT *)adev->gfx.rlc.rlc_toc_buf;
        while (rlc_toc && (rlc_toc->id > FIRMWARE_ID_INVALID) &&
@@ -7608,10 +7723,8 @@ static int gfx_v10_0_soft_reset(void *handle)
 
 static uint64_t gfx_v10_0_get_gpu_clock_counter(struct amdgpu_device *adev)
 {
-       uint64_t clock;
+       uint64_t clock, clock_lo, clock_hi, hi_check;
 
-       amdgpu_gfx_off_ctrl(adev, false);
-       mutex_lock(&adev->gfx.gpu_clock_mutex);
        switch (adev->asic_type) {
        case CHIP_VANGOGH:
        case CHIP_YELLOW_CARP:
@@ -7619,12 +7732,21 @@ static uint64_t gfx_v10_0_get_gpu_clock_counter(struct amdgpu_device *adev)
                        ((uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Vangogh) << 32ULL);
                break;
        default:
-               clock = (uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER) |
-                       ((uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER) << 32ULL);
+               preempt_disable();
+               clock_hi = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER);
+               clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER);
+               hi_check = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER);
+               /* The SMUIO TSC clock frequency is 100MHz, which sets 32-bit carry over
+                * roughly every 42 seconds.
+                */
+               if (hi_check != clock_hi) {
+                       clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER);
+                       clock_hi = hi_check;
+               }
+               preempt_enable();
+               clock = clock_lo | (clock_hi << 32ULL);
                break;
        }
-       mutex_unlock(&adev->gfx.gpu_clock_mutex);
-       amdgpu_gfx_off_ctrl(adev, true);
        return clock;
 }
 
@@ -7665,6 +7787,7 @@ static int gfx_v10_0_early_init(void *handle)
        case CHIP_NAVI10:
        case CHIP_NAVI14:
        case CHIP_NAVI12:
+       case CHIP_CYAN_SKILLFISH:
                adev->gfx.num_gfx_rings = GFX10_NUM_GFX_RINGS_NV1X;
                break;
        case CHIP_SIENNA_CICHLID:
@@ -8261,8 +8384,8 @@ static const struct amdgpu_rlc_funcs gfx_v10_0_rlc_funcs_sriov = {
        .reset = gfx_v10_0_rlc_reset,
        .start = gfx_v10_0_rlc_start,
        .update_spm_vmid = gfx_v10_0_update_spm_vmid,
-       .rlcg_wreg = gfx_v10_rlcg_wreg,
-       .rlcg_rreg = gfx_v10_rlcg_rreg,
+       .sriov_wreg = gfx_v10_sriov_wreg,
+       .sriov_rreg = gfx_v10_sriov_rreg,
        .is_rlcg_access_range = gfx_v10_0_is_rlcg_access_range,
 };
 
@@ -9425,6 +9548,7 @@ static void gfx_v10_0_set_rlc_funcs(struct amdgpu_device *adev)
        case CHIP_DIMGREY_CAVEFISH:
        case CHIP_BEIGE_GOBY:
        case CHIP_YELLOW_CARP:
+       case CHIP_CYAN_SKILLFISH:
                adev->gfx.rlc.funcs = &gfx_v10_0_rlc_funcs;
                break;
        case CHIP_NAVI12:
index 044076ec1d03632e5c1ab5a9b808f9d2d4f2519e..03acc777adf7e0e26a826c28b225eb7c5cf759cd 100644 (file)
@@ -787,7 +787,7 @@ static void gfx_v9_0_rlcg_w(struct amdgpu_device *adev, u32 offset, u32 v, u32 f
 
 }
 
-static void gfx_v9_0_rlcg_wreg(struct amdgpu_device *adev, u32 offset,
+static void gfx_v9_0_sriov_wreg(struct amdgpu_device *adev, u32 offset,
                               u32 v, u32 acc_flags, u32 hwip)
 {
        if ((acc_flags & AMDGPU_REGS_RLC) &&
@@ -5131,7 +5131,7 @@ static const struct amdgpu_rlc_funcs gfx_v9_0_rlc_funcs = {
        .reset = gfx_v9_0_rlc_reset,
        .start = gfx_v9_0_rlc_start,
        .update_spm_vmid = gfx_v9_0_update_spm_vmid,
-       .rlcg_wreg = gfx_v9_0_rlcg_wreg,
+       .sriov_wreg = gfx_v9_0_sriov_wreg,
        .is_rlcg_access_range = gfx_v9_0_is_rlcg_access_range,
 };
 
index 4523df2785d633b4812bce43604c14bdc2f39db0..24b781e90befa5cc6ad2b018ef097d7b0e4e4db7 100644 (file)
@@ -810,6 +810,7 @@ static int gmc_v10_0_mc_init(struct amdgpu_device *adev)
                case CHIP_DIMGREY_CAVEFISH:
                case CHIP_BEIGE_GOBY:
                case CHIP_YELLOW_CARP:
+               case CHIP_CYAN_SKILLFISH:
                default:
                        adev->gmc.gart_size = 512ULL << 20;
                        break;
@@ -879,6 +880,7 @@ static int gmc_v10_0_sw_init(void *handle)
        case CHIP_DIMGREY_CAVEFISH:
        case CHIP_BEIGE_GOBY:
        case CHIP_YELLOW_CARP:
+       case CHIP_CYAN_SKILLFISH:
                adev->num_vmhubs = 2;
                /*
                 * To fulfill 4-level page support,
@@ -996,6 +998,7 @@ static void gmc_v10_0_init_golden_registers(struct amdgpu_device *adev)
        case CHIP_DIMGREY_CAVEFISH:
        case CHIP_BEIGE_GOBY:
        case CHIP_YELLOW_CARP:
+       case CHIP_CYAN_SKILLFISH:
                break;
        default:
                break;
index 7eb70d69f76056680d9cc82b46ed54d0ff33b800..7cf653f9e9a72395c72249bcc93063bc2655c47c 100644 (file)
@@ -53,6 +53,7 @@
 #include "mmhub_v1_7.h"
 #include "umc_v6_1.h"
 #include "umc_v6_0.h"
+#include "umc_v6_7.h"
 #include "hdp_v4_0.h"
 
 #include "ivsrcid/vmc/irqsrcs_vmc_1_0.h"
@@ -1168,6 +1169,18 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
                adev->umc.channel_idx_tbl = &umc_v6_1_channel_idx_tbl[0][0];
                adev->umc.ras_funcs = &umc_v6_1_ras_funcs;
                break;
+       case CHIP_ALDEBARAN:
+               adev->umc.max_ras_err_cnt_per_query = UMC_V6_7_TOTAL_CHANNEL_NUM;
+               adev->umc.channel_inst_num = UMC_V6_7_UMC_INSTANCE_NUM;
+               adev->umc.umc_inst_num = UMC_V6_7_CHANNEL_INSTANCE_NUM;
+               adev->umc.channel_offs = UMC_V6_7_PER_CHANNEL_OFFSET;
+               if (!adev->gmc.xgmi.connected_to_cpu)
+                       adev->umc.ras_funcs = &umc_v6_7_ras_funcs;
+               if (1 & adev->smuio.funcs->get_die_id(adev))
+                       adev->umc.channel_idx_tbl = &umc_v6_7_channel_idx_tbl_first[0][0];
+               else
+                       adev->umc.channel_idx_tbl = &umc_v6_7_channel_idx_tbl_second[0][0];
+               break;
        default:
                break;
        }
index 7b79eeaa88aa65fee7002a8b9cb56a218e3e3709..b184b656b9b6b93b92b9e8ee6d17b3a53cdb9df3 100644 (file)
@@ -508,6 +508,26 @@ static void nbio_v2_3_apply_l1_link_width_reconfig_wa(struct amdgpu_device *adev
        WREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL, reg_data);
 }
 
+static void nbio_v2_3_clear_doorbell_interrupt(struct amdgpu_device *adev)
+{
+       uint32_t reg, reg_data;
+
+       if (adev->asic_type != CHIP_SIENNA_CICHLID)
+               return;
+
+       reg = RREG32_SOC15(NBIO, 0, mmBIF_RB_CNTL);
+
+       /* Clear Interrupt Status
+        */
+       if ((reg & BIF_RB_CNTL__RB_ENABLE_MASK) == 0) {
+               reg = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL);
+               if (reg & BIF_DOORBELL_INT_CNTL__DOORBELL_INTERRUPT_STATUS_MASK) {
+                       reg_data = 1 << BIF_DOORBELL_INT_CNTL__DOORBELL_INTERRUPT_CLEAR__SHIFT;
+                       WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, reg_data);
+               }
+       }
+}
+
 const struct amdgpu_nbio_funcs nbio_v2_3_funcs = {
        .get_hdp_flush_req_offset = nbio_v2_3_get_hdp_flush_req_offset,
        .get_hdp_flush_done_offset = nbio_v2_3_get_hdp_flush_done_offset,
@@ -531,4 +551,5 @@ const struct amdgpu_nbio_funcs nbio_v2_3_funcs = {
        .program_aspm =  nbio_v2_3_program_aspm,
        .apply_lc_spc_mode_wa = nbio_v2_3_apply_lc_spc_mode_wa,
        .apply_l1_link_width_reconfig_wa = nbio_v2_3_apply_l1_link_width_reconfig_wa,
+       .clear_doorbell_interrupt = nbio_v2_3_clear_doorbell_interrupt,
 };
index 94d029dbf30da5c802493ccde07c36972ca5fc84..436fb13e32f0e78dc4b7b850eb5cabc79488aae7 100644 (file)
@@ -666,6 +666,9 @@ legacy_init:
        case CHIP_YELLOW_CARP:
                yellow_carp_reg_base_init(adev);
                break;
+       case CHIP_CYAN_SKILLFISH:
+               cyan_skillfish_reg_base_init(adev);
+               break;
        default:
                return -EINVAL;
        }
@@ -682,7 +685,10 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 {
        int r;
 
-       if (adev->flags & AMD_IS_APU) {
+       if (adev->asic_type == CHIP_CYAN_SKILLFISH) {
+               adev->nbio.funcs = &nbio_v2_3_funcs;
+               adev->nbio.hdp_flush_reg = &nbio_v2_3_hdp_flush_reg;
+       } else if (adev->flags & AMD_IS_APU) {
                adev->nbio.funcs = &nbio_v7_2_funcs;
                adev->nbio.hdp_flush_reg = &nbio_v7_2_hdp_flush_reg;
        } else {
@@ -889,6 +895,20 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
                amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
                amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block);
                break;
+       case CHIP_CYAN_SKILLFISH:
+               amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
+               amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
+               amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
+               if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) {
+                       if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
+                               amdgpu_device_ip_block_add(adev, &psp_v11_0_8_ip_block);
+                       amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
+               }
+               if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
+                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+               amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
+               amdgpu_device_ip_block_add(adev, &sdma_v5_0_ip_block);
+               break;
        default:
                return -EINVAL;
        }
@@ -1241,6 +1261,11 @@ static int nv_common_early_init(void *handle)
                else
                        adev->external_rev_id = adev->rev_id + 0x01;
                break;
+       case CHIP_CYAN_SKILLFISH:
+               adev->cg_flags = 0;
+               adev->pg_flags = 0;
+               adev->external_rev_id = adev->rev_id + 0x82;
+               break;
        default:
                /* FIXME: not supported yet */
                return -EINVAL;
index eb9aff1e7253daefeceaa87cea8491a3d96b54bd..1f40ba3b04606441b3f50db1e32b9a51c74843f5 100644 (file)
@@ -38,5 +38,6 @@ void vangogh_reg_base_init(struct amdgpu_device *adev);
 int dimgrey_cavefish_reg_base_init(struct amdgpu_device *adev);
 int beige_goby_reg_base_init(struct amdgpu_device *adev);
 int yellow_carp_reg_base_init(struct amdgpu_device *adev);
+int cyan_skillfish_reg_base_init(struct amdgpu_device *adev);
 
 #endif
index bc133db2d538b255e740dee333df6d34fc1b1957..8862684f8b43bc44da7388fbb1ebcefb22ccefad 100644 (file)
@@ -80,6 +80,9 @@ MODULE_FIRMWARE("amdgpu/beige_goby_ta.bin");
 /* For large FW files the time to complete can be very long */
 #define USBC_PD_POLLING_LIMIT_S 240
 
+/* Read USB-PD from LFB */
+#define GFX_CMD_USB_PD_USE_LFB 0x480
+
 static int psp_v11_0_init_microcode(struct psp_context *psp)
 {
        struct amdgpu_device *adev = psp->adev;
@@ -284,7 +287,7 @@ static int psp_v11_0_bootloader_load_kdb(struct psp_context *psp)
                return ret;
 
        /* Copy PSP KDB binary to memory */
-       psp_copy_fw(psp, psp->kdb_start_addr, psp->kdb_bin_size);
+       psp_copy_fw(psp, psp->kdb.start_addr, psp->kdb.size_bytes);
 
        /* Provide the PSP KDB to bootloader */
        WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -315,7 +318,7 @@ static int psp_v11_0_bootloader_load_spl(struct psp_context *psp)
                return ret;
 
        /* Copy PSP SPL binary to memory */
-       psp_copy_fw(psp, psp->spl_start_addr, psp->spl_bin_size);
+       psp_copy_fw(psp, psp->spl.start_addr, psp->spl.size_bytes);
 
        /* Provide the PSP SPL to bootloader */
        WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -346,7 +349,7 @@ static int psp_v11_0_bootloader_load_sysdrv(struct psp_context *psp)
                return ret;
 
        /* Copy PSP System Driver binary to memory */
-       psp_copy_fw(psp, psp->sys_start_addr, psp->sys_bin_size);
+       psp_copy_fw(psp, psp->sys.start_addr, psp->sys.size_bytes);
 
        /* Provide the sys driver to bootloader */
        WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -380,7 +383,7 @@ static int psp_v11_0_bootloader_load_sos(struct psp_context *psp)
                return ret;
 
        /* Copy Secure OS binary to PSP memory */
-       psp_copy_fw(psp, psp->sos_start_addr, psp->sos_bin_size);
+       psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes);
 
        /* Provide the PSP secure OS to bootloader */
        WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -753,44 +756,26 @@ static void psp_v11_0_ring_set_wptr(struct psp_context *psp, uint32_t value)
                WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, value);
 }
 
-static int psp_v11_0_load_usbc_pd_fw(struct psp_context *psp, dma_addr_t dma_addr)
+static int psp_v11_0_load_usbc_pd_fw(struct psp_context *psp, uint64_t fw_pri_mc_addr)
 {
        struct amdgpu_device *adev = psp->adev;
        uint32_t reg_status;
        int ret, i = 0;
 
-       /* Write lower 32-bit address of the PD Controller FW */
-       WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, lower_32_bits(dma_addr));
-       ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
-                            0x80000000, 0x80000000, false);
-       if (ret)
-               return ret;
-
-       /* Fireup interrupt so PSP can pick up the lower address */
-       WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, 0x800000);
-       ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
-                            0x80000000, 0x80000000, false);
-       if (ret)
-               return ret;
-
-       reg_status = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35);
-
-       if ((reg_status & 0xFFFF) != 0) {
-               DRM_ERROR("Lower address load failed - MP0_SMN_C2PMSG_35.Bits [15:0] = %02x...\n",
-                               reg_status & 0xFFFF);
-               return -EIO;
-       }
-
-       /* Write upper 32-bit address of the PD Controller FW */
-       WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, upper_32_bits(dma_addr));
+       /*
+        * LFB address which is aligned to 1MB address and has to be
+        * right-shifted by 20 so that LFB address can be passed on a 32-bit C2P
+        * register
+        */
+       WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, (fw_pri_mc_addr >> 20));
 
        ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
                             0x80000000, 0x80000000, false);
        if (ret)
                return ret;
 
-       /* Fireup interrupt so PSP can pick up the upper address */
-       WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, 0x4000000);
+       /* Fireup interrupt so PSP can pick up the address */
+       WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, (GFX_CMD_USB_PD_USE_LFB << 16));
 
        /* FW load takes very long time */
        do {
@@ -806,7 +791,7 @@ static int psp_v11_0_load_usbc_pd_fw(struct psp_context *psp, dma_addr_t dma_add
 done:
 
        if ((reg_status & 0xFFFF) != 0) {
-               DRM_ERROR("Upper address load failed - MP0_SMN_C2PMSG_35.Bits [15:0] = x%04x\n",
+               DRM_ERROR("Address load failed - MP0_SMN_C2PMSG_35.Bits [15:0] = 0x%04x\n",
                                reg_status & 0xFFFF);
                return -EIO;
        }
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.c
new file mode 100644 (file)
index 0000000..ff13e1b
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "amdgpu.h"
+#include "amdgpu_psp.h"
+#include "amdgpu_ucode.h"
+#include "soc15_common.h"
+#include "psp_v11_0_8.h"
+
+#include "mp/mp_11_0_8_offset.h"
+
+static int psp_v11_0_8_ring_init(struct psp_context *psp,
+                             enum psp_ring_type ring_type)
+{
+       int ret = 0;
+       struct psp_ring *ring;
+       struct amdgpu_device *adev = psp->adev;
+
+       ring = &psp->km_ring;
+
+       ring->ring_type = ring_type;
+
+       /* allocate 4k Page of Local Frame Buffer memory for ring */
+       ring->ring_size = 0x1000;
+       ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE,
+                                     AMDGPU_GEM_DOMAIN_VRAM,
+                                     &adev->firmware.rbuf,
+                                     &ring->ring_mem_mc_addr,
+                                     (void **)&ring->ring_mem);
+       if (ret) {
+               ring->ring_size = 0;
+               return ret;
+       }
+
+       return 0;
+}
+
+static int psp_v11_0_8_ring_stop(struct psp_context *psp,
+                              enum psp_ring_type ring_type)
+{
+       int ret = 0;
+       struct amdgpu_device *adev = psp->adev;
+
+       if (amdgpu_sriov_vf(adev)) {
+               /* Write the ring destroy command*/
+               WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101,
+                            GFX_CTRL_CMD_ID_DESTROY_GPCOM_RING);
+               /* there might be handshake issue with hardware which needs delay */
+               mdelay(20);
+               /* Wait for response flag (bit 31) */
+               ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
+                                  0x80000000, 0x80000000, false);
+       } else {
+               /* Write the ring destroy command*/
+               WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64,
+                            GFX_CTRL_CMD_ID_DESTROY_RINGS);
+               /* there might be handshake issue with hardware which needs delay */
+               mdelay(20);
+               /* Wait for response flag (bit 31) */
+               ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
+                                  0x80000000, 0x80000000, false);
+       }
+
+       return ret;
+}
+
+static int psp_v11_0_8_ring_create(struct psp_context *psp,
+                                enum psp_ring_type ring_type)
+{
+       int ret = 0;
+       unsigned int psp_ring_reg = 0;
+       struct psp_ring *ring = &psp->km_ring;
+       struct amdgpu_device *adev = psp->adev;
+
+       if (amdgpu_sriov_vf(adev)) {
+               ret = psp_v11_0_8_ring_stop(psp, ring_type);
+               if (ret) {
+                       DRM_ERROR("psp_v11_0_8_ring_stop_sriov failed!\n");
+                       return ret;
+               }
+
+               /* Write low address of the ring to C2PMSG_102 */
+               psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr);
+               WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, psp_ring_reg);
+               /* Write high address of the ring to C2PMSG_103 */
+               psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr);
+               WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_103, psp_ring_reg);
+
+               /* Write the ring initialization command to C2PMSG_101 */
+               WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101,
+                            GFX_CTRL_CMD_ID_INIT_GPCOM_RING);
+
+               /* there might be handshake issue with hardware which needs delay */
+               mdelay(20);
+
+               /* Wait for response flag (bit 31) in C2PMSG_101 */
+               ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
+                                  0x80000000, 0x8000FFFF, false);
+
+       } else {
+               /* Wait for sOS ready for ring creation */
+               ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
+                                  0x80000000, 0x80000000, false);
+               if (ret) {
+                       DRM_ERROR("Failed to wait for trust OS ready for ring creation\n");
+                       return ret;
+               }
+
+               /* Write low address of the ring to C2PMSG_69 */
+               psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr);
+               WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_69, psp_ring_reg);
+               /* Write high address of the ring to C2PMSG_70 */
+               psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr);
+               WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_70, psp_ring_reg);
+               /* Write size of ring to C2PMSG_71 */
+               psp_ring_reg = ring->ring_size;
+               WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_71, psp_ring_reg);
+               /* Write the ring initialization command to C2PMSG_64 */
+               psp_ring_reg = ring_type;
+               psp_ring_reg = psp_ring_reg << 16;
+               WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, psp_ring_reg);
+
+               /* there might be handshake issue with hardware which needs delay */
+               mdelay(20);
+
+               /* Wait for response flag (bit 31) in C2PMSG_64 */
+               ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
+                                  0x80000000, 0x8000FFFF, false);
+       }
+
+       return ret;
+}
+
+static int psp_v11_0_8_ring_destroy(struct psp_context *psp,
+                                 enum psp_ring_type ring_type)
+{
+       int ret = 0;
+       struct psp_ring *ring = &psp->km_ring;
+       struct amdgpu_device *adev = psp->adev;
+
+       ret = psp_v11_0_8_ring_stop(psp, ring_type);
+       if (ret)
+               DRM_ERROR("Fail to stop psp ring\n");
+
+       amdgpu_bo_free_kernel(&adev->firmware.rbuf,
+                             &ring->ring_mem_mc_addr,
+                             (void **)&ring->ring_mem);
+
+       return ret;
+}
+
+static uint32_t psp_v11_0_8_ring_get_wptr(struct psp_context *psp)
+{
+       uint32_t data;
+       struct amdgpu_device *adev = psp->adev;
+
+       if (amdgpu_sriov_vf(adev))
+               data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102);
+       else
+               data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67);
+
+       return data;
+}
+
+static void psp_v11_0_8_ring_set_wptr(struct psp_context *psp, uint32_t value)
+{
+       struct amdgpu_device *adev = psp->adev;
+
+       if (amdgpu_sriov_vf(adev)) {
+               WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, value);
+               WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101,
+                            GFX_CTRL_CMD_ID_CONSUME_CMD);
+       } else
+               WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, value);
+}
+
+static const struct psp_funcs psp_v11_0_8_funcs = {
+       .ring_init = psp_v11_0_8_ring_init,
+       .ring_create = psp_v11_0_8_ring_create,
+       .ring_stop = psp_v11_0_8_ring_stop,
+       .ring_destroy = psp_v11_0_8_ring_destroy,
+       .ring_get_wptr = psp_v11_0_8_ring_get_wptr,
+       .ring_set_wptr = psp_v11_0_8_ring_set_wptr,
+};
+
+void psp_v11_0_8_set_psp_funcs(struct psp_context *psp)
+{
+       psp->funcs = &psp_v11_0_8_funcs;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.h b/drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.h
new file mode 100644 (file)
index 0000000..890377a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef __PSP_V11_0_8_H__
+#define __PSP_V11_0_8_H__
+
+#include "amdgpu_psp.h"
+
+void psp_v11_0_8_set_psp_funcs(struct psp_context *psp);
+
+#endif
index 618e5b6b85d99df005f01a79d2925eefb65aa7b8..0c908d4566e8ce4f427e4dacb8a7494ef988d506 100644 (file)
@@ -67,7 +67,7 @@ static int psp_v12_0_init_microcode(struct psp_context *psp)
 
        err = psp_init_asd_microcode(psp, chip_name);
        if (err)
-               goto out;
+               return err;
 
        snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
        err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
@@ -80,7 +80,7 @@ static int psp_v12_0_init_microcode(struct psp_context *psp)
        } else {
                err = amdgpu_ucode_validate(adev->psp.ta_fw);
                if (err)
-                       goto out2;
+                       goto out;
 
                ta_hdr = (const struct ta_firmware_header_v1_0 *)
                                 adev->psp.ta_fw->data;
@@ -105,10 +105,9 @@ static int psp_v12_0_init_microcode(struct psp_context *psp)
 
        return 0;
 
-out2:
+out:
        release_firmware(adev->psp.ta_fw);
        adev->psp.ta_fw = NULL;
-out:
        if (err) {
                dev_err(adev->dev,
                        "psp v12.0: Failed to load firmware \"%s\"\n",
@@ -139,7 +138,7 @@ static int psp_v12_0_bootloader_load_sysdrv(struct psp_context *psp)
                return ret;
 
        /* Copy PSP System Driver binary to memory */
-       psp_copy_fw(psp, psp->sys_start_addr, psp->sys_bin_size);
+       psp_copy_fw(psp, psp->sys.start_addr, psp->sys.size_bytes);
 
        /* Provide the sys driver to bootloader */
        WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -178,7 +177,7 @@ static int psp_v12_0_bootloader_load_sos(struct psp_context *psp)
                return ret;
 
        /* Copy Secure OS binary to PSP memory */
-       psp_copy_fw(psp, psp->sos_start_addr, psp->sos_bin_size);
+       psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes);
 
        /* Provide the PSP secure OS to bootloader */
        WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
index c8949add88f3831bfcc6f9cc053e19312ce0652c..47a500f64db2052901f6845f5206700f26735ded 100644 (file)
@@ -35,6 +35,12 @@ MODULE_FIRMWARE("amdgpu/yellow_carp_asd.bin");
 MODULE_FIRMWARE("amdgpu/yellow_carp_toc.bin");
 MODULE_FIRMWARE("amdgpu/yellow_carp_ta.bin");
 
+/* For large FW files the time to complete can be very long */
+#define USBC_PD_POLLING_LIMIT_S 240
+
+/* Read USB-PD from LFB */
+#define GFX_CMD_USB_PD_USE_LFB 0x480
+
 static int psp_v13_0_init_microcode(struct psp_context *psp)
 {
        struct amdgpu_device *adev = psp->adev;
@@ -111,7 +117,9 @@ static int psp_v13_0_wait_for_bootloader(struct psp_context *psp)
        return ret;
 }
 
-static int psp_v13_0_bootloader_load_kdb(struct psp_context *psp)
+static int psp_v13_0_bootloader_load_component(struct psp_context      *psp,
+                                              struct psp_bin_desc      *bin_desc,
+                                              enum psp_bootloader_cmd  bl_cmd)
 {
        int ret;
        uint32_t psp_gfxdrv_command_reg = 0;
@@ -130,12 +138,12 @@ static int psp_v13_0_bootloader_load_kdb(struct psp_context *psp)
        memset(psp->fw_pri_buf, 0, PSP_1_MEG);
 
        /* Copy PSP KDB binary to memory */
-       memcpy(psp->fw_pri_buf, psp->kdb_start_addr, psp->kdb_bin_size);
+       memcpy(psp->fw_pri_buf, bin_desc->start_addr, bin_desc->size_bytes);
 
        /* Provide the PSP KDB to bootloader */
        WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36,
               (uint32_t)(psp->fw_pri_mc_addr >> 20));
-       psp_gfxdrv_command_reg = PSP_BL__LOAD_KEY_DATABASE;
+       psp_gfxdrv_command_reg = bl_cmd;
        WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35,
               psp_gfxdrv_command_reg);
 
@@ -144,40 +152,29 @@ static int psp_v13_0_bootloader_load_kdb(struct psp_context *psp)
        return ret;
 }
 
-static int psp_v13_0_bootloader_load_sysdrv(struct psp_context *psp)
+static int psp_v13_0_bootloader_load_kdb(struct psp_context *psp)
 {
-       int ret;
-       uint32_t psp_gfxdrv_command_reg = 0;
-       struct amdgpu_device *adev = psp->adev;
-
-       /* Check sOS sign of life register to confirm sys driver and sOS
-        * are already been loaded.
-        */
-       if (psp_v13_0_is_sos_alive(psp))
-               return 0;
-
-       ret = psp_v13_0_wait_for_bootloader(psp);
-       if (ret)
-               return ret;
-
-       memset(psp->fw_pri_buf, 0, PSP_1_MEG);
-
-       /* Copy PSP System Driver binary to memory */
-       memcpy(psp->fw_pri_buf, psp->sys_start_addr, psp->sys_bin_size);
+       return psp_v13_0_bootloader_load_component(psp, &psp->kdb, PSP_BL__LOAD_KEY_DATABASE);
+}
 
-       /* Provide the sys driver to bootloader */
-       WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36,
-              (uint32_t)(psp->fw_pri_mc_addr >> 20));
-       psp_gfxdrv_command_reg = PSP_BL__LOAD_SYSDRV;
-       WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35,
-              psp_gfxdrv_command_reg);
+static int psp_v13_0_bootloader_load_sysdrv(struct psp_context *psp)
+{
+       return psp_v13_0_bootloader_load_component(psp, &psp->sys, PSP_BL__LOAD_SYSDRV);
+}
 
-       /* there might be handshake issue with hardware which needs delay */
-       mdelay(20);
+static int psp_v13_0_bootloader_load_soc_drv(struct psp_context *psp)
+{
+       return psp_v13_0_bootloader_load_component(psp, &psp->soc_drv, PSP_BL__LOAD_SOCDRV);
+}
 
-       ret = psp_v13_0_wait_for_bootloader(psp);
+static int psp_v13_0_bootloader_load_intf_drv(struct psp_context *psp)
+{
+       return psp_v13_0_bootloader_load_component(psp, &psp->intf_drv, PSP_BL__LOAD_INTFDRV);
+}
 
-       return ret;
+static int psp_v13_0_bootloader_load_dbg_drv(struct psp_context *psp)
+{
+       return psp_v13_0_bootloader_load_component(psp, &psp->dbg_drv, PSP_BL__LOAD_DBGDRV);
 }
 
 static int psp_v13_0_bootloader_load_sos(struct psp_context *psp)
@@ -199,7 +196,7 @@ static int psp_v13_0_bootloader_load_sos(struct psp_context *psp)
        memset(psp->fw_pri_buf, 0, PSP_1_MEG);
 
        /* Copy Secure OS binary to PSP memory */
-       memcpy(psp->fw_pri_buf, psp->sos_start_addr, psp->sos_bin_size);
+       memcpy(psp->fw_pri_buf, psp->sos.start_addr, psp->sos.size_bytes);
 
        /* Provide the PSP secure OS to bootloader */
        WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36,
@@ -382,10 +379,71 @@ static void psp_v13_0_ring_set_wptr(struct psp_context *psp, uint32_t value)
                WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_67, value);
 }
 
+static int psp_v13_0_load_usbc_pd_fw(struct psp_context *psp, uint64_t fw_pri_mc_addr)
+{
+       struct amdgpu_device *adev = psp->adev;
+       uint32_t reg_status;
+       int ret, i = 0;
+
+       /*
+        * LFB address which is aligned to 1MB address and has to be
+        * right-shifted by 20 so that LFB address can be passed on a 32-bit C2P
+        * register
+        */
+       WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36, (fw_pri_mc_addr >> 20));
+
+       ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35),
+                            0x80000000, 0x80000000, false);
+       if (ret)
+               return ret;
+
+       /* Fireup interrupt so PSP can pick up the address */
+       WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35, (GFX_CMD_USB_PD_USE_LFB << 16));
+
+       /* FW load takes very long time */
+       do {
+               msleep(1000);
+               reg_status = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35);
+
+               if (reg_status & 0x80000000)
+                       goto done;
+
+       } while (++i < USBC_PD_POLLING_LIMIT_S);
+
+       return -ETIME;
+done:
+
+       if ((reg_status & 0xFFFF) != 0) {
+               DRM_ERROR("Address load failed - MP0_SMN_C2PMSG_35.Bits [15:0] = %04x\n",
+                               reg_status & 0xFFFF);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int psp_v13_0_read_usbc_pd_fw(struct psp_context *psp, uint32_t *fw_ver)
+{
+       struct amdgpu_device *adev = psp->adev;
+       int ret;
+
+       WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35, C2PMSG_CMD_GFX_USB_PD_FW_VER);
+
+       ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35),
+                                    0x80000000, 0x80000000, false);
+       if (!ret)
+               *fw_ver = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36);
+
+       return ret;
+}
+
 static const struct psp_funcs psp_v13_0_funcs = {
        .init_microcode = psp_v13_0_init_microcode,
        .bootloader_load_kdb = psp_v13_0_bootloader_load_kdb,
        .bootloader_load_sysdrv = psp_v13_0_bootloader_load_sysdrv,
+       .bootloader_load_soc_drv = psp_v13_0_bootloader_load_soc_drv,
+       .bootloader_load_intf_drv = psp_v13_0_bootloader_load_intf_drv,
+       .bootloader_load_dbg_drv = psp_v13_0_bootloader_load_dbg_drv,
        .bootloader_load_sos = psp_v13_0_bootloader_load_sos,
        .ring_init = psp_v13_0_ring_init,
        .ring_create = psp_v13_0_ring_create,
@@ -393,6 +451,8 @@ static const struct psp_funcs psp_v13_0_funcs = {
        .ring_destroy = psp_v13_0_ring_destroy,
        .ring_get_wptr = psp_v13_0_ring_get_wptr,
        .ring_set_wptr = psp_v13_0_ring_set_wptr,
+       .load_usbc_pd_fw = psp_v13_0_load_usbc_pd_fw,
+       .read_usbc_pd_fw = psp_v13_0_read_usbc_pd_fw
 };
 
 void psp_v13_0_set_psp_funcs(struct psp_context *psp)
index b86dcbabb6352d59b58fad7c9fac13e0644f5b6a..1ed357cb0f49014a18afa78d4b6ad42abe8295bb 100644 (file)
@@ -103,7 +103,7 @@ static int psp_v3_1_bootloader_load_sysdrv(struct psp_context *psp)
                return ret;
 
        /* Copy PSP System Driver binary to memory */
-       psp_copy_fw(psp, psp->sys_start_addr, psp->sys_bin_size);
+       psp_copy_fw(psp, psp->sys.start_addr, psp->sys.size_bytes);
 
        /* Provide the sys driver to bootloader */
        WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -142,7 +142,7 @@ static int psp_v3_1_bootloader_load_sos(struct psp_context *psp)
                return ret;
 
        /* Copy Secure OS binary to PSP memory */
-       psp_copy_fw(psp, psp->sos_start_addr, psp->sos_bin_size);
+       psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes);
 
        /* Provide the PSP secure OS to bootloader */
        WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
index 6117ba8a4c3fdc4df7443cfd85d6ee9ed316cfae..50bf3b71bc93c2381db6f36408e3c25a1ad5b505 100644 (file)
@@ -51,6 +51,12 @@ MODULE_FIRMWARE("amdgpu/navi14_sdma1.bin");
 MODULE_FIRMWARE("amdgpu/navi12_sdma.bin");
 MODULE_FIRMWARE("amdgpu/navi12_sdma1.bin");
 
+MODULE_FIRMWARE("amdgpu/cyan_skillfish_sdma.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish_sdma1.bin");
+
+MODULE_FIRMWARE("amdgpu/cyan_skillfish2_sdma.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish2_sdma1.bin");
+
 #define SDMA1_REG_OFFSET 0x600
 #define SDMA0_HYP_DEC_REG_START 0x5880
 #define SDMA0_HYP_DEC_REG_END 0x5893
@@ -130,6 +136,37 @@ static const struct soc15_reg_golden golden_settings_sdma_nv12[] = {
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC3_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
 };
 
+static const struct soc15_reg_golden golden_settings_sdma_cyan_skillfish[] = {
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_CHICKEN_BITS, 0xffbf1f0f, 0x03ab0107),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_GB_ADDR_CONFIG, 0x001877ff, 0x00000044),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x001877ff, 0x00000044),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_GFX_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_PAGE_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC2_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC3_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC4_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC5_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC6_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC7_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_UTCL1_PAGE, 0x007fffff, 0x004c5c00),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_CHICKEN_BITS, 0xffbf1f0f, 0x03ab0107),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_GB_ADDR_CONFIG, 0x001877ff, 0x00000044),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x001877ff, 0x00000044),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_GFX_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_PAGE_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC2_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC3_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC4_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC5_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC6_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC7_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_UTCL1_PAGE, 0x007fffff, 0x004c5c00)
+};
+
 static u32 sdma_v5_0_get_reg_offset(struct amdgpu_device *adev, u32 instance, u32 internal_offset)
 {
        u32 base;
@@ -180,6 +217,11 @@ static void sdma_v5_0_init_golden_registers(struct amdgpu_device *adev)
                                                golden_settings_sdma_nv12,
                                                (const u32)ARRAY_SIZE(golden_settings_sdma_nv12));
                break;
+       case CHIP_CYAN_SKILLFISH:
+               soc15_program_register_sequence(adev,
+                                               golden_settings_sdma_cyan_skillfish,
+                                               (const u32)ARRAY_SIZE(golden_settings_sdma_cyan_skillfish));
+               break;
        default:
                break;
        }
@@ -200,7 +242,7 @@ static void sdma_v5_0_init_golden_registers(struct amdgpu_device *adev)
 static int sdma_v5_0_init_microcode(struct amdgpu_device *adev)
 {
        const char *chip_name;
-       char fw_name[30];
+       char fw_name[40];
        int err = 0, i;
        struct amdgpu_firmware_info *info = NULL;
        const struct common_firmware_header *header = NULL;
@@ -221,6 +263,12 @@ static int sdma_v5_0_init_microcode(struct amdgpu_device *adev)
        case CHIP_NAVI12:
                chip_name = "navi12";
                break;
+       case CHIP_CYAN_SKILLFISH:
+               if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2)
+                       chip_name = "cyan_skillfish2";
+               else
+                       chip_name = "cyan_skillfish";
+               break;
        default:
                BUG();
        }
index 7486e5306786793e4df70f311cb46762475ff6b8..779f5c911e1123188d075f4973877a5aec2d2bc1 100644 (file)
@@ -87,21 +87,6 @@ static u32 sdma_v5_2_get_reg_offset(struct amdgpu_device *adev, u32 instance, u3
        return base + internal_offset;
 }
 
-static void sdma_v5_2_init_golden_registers(struct amdgpu_device *adev)
-{
-       switch (adev->asic_type) {
-       case CHIP_SIENNA_CICHLID:
-       case CHIP_NAVY_FLOUNDER:
-       case CHIP_VANGOGH:
-       case CHIP_DIMGREY_CAVEFISH:
-       case CHIP_BEIGE_GOBY:
-       case CHIP_YELLOW_CARP:
-               break;
-       default:
-               break;
-       }
-}
-
 static int sdma_v5_2_init_inst_ctx(struct amdgpu_sdma_instance *sdma_inst)
 {
        int err = 0;
@@ -1345,8 +1330,6 @@ static int sdma_v5_2_hw_init(void *handle)
        int r;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       sdma_v5_2_init_golden_registers(adev);
-
        r = sdma_v5_2_start(adev);
 
        return r;
index 5c7d769aee3fbadd25fa16dc38ea5fafa674f24e..73ffa8fde3df3f3fbc2d1abf79651c87c6b68329 100644 (file)
@@ -41,9 +41,7 @@
 #define I2C_SW_TIMEOUT        8
 #define I2C_ABORT             0x10
 
-/* I2C transaction flags */
-#define I2C_NO_STOP    1
-#define I2C_RESTART    2
+#define I2C_X_RESTART         BIT(31)
 
 #define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
 
@@ -56,12 +54,48 @@ static void smu_v11_0_i2c_set_clock_gating(struct i2c_adapter *control, bool en)
        WREG32_SOC15(SMUIO, 0, mmSMUIO_PWRMGT, reg);
 }
 
+/* The T_I2C_POLL_US is defined as follows:
+ *
+ * "Define a timer interval (t_i2c_poll) equal to 10 times the
+ *  signalling period for the highest I2C transfer speed used in the
+ *  system and supported by DW_apb_i2c. For instance, if the highest
+ *  I2C data transfer mode is 400 kb/s, then t_i2c_poll is 25 us."  --
+ * DesignWare DW_apb_i2c Databook, Version 1.21a, section 3.8.3.1,
+ * page 56, with grammar and syntax corrections.
+ *
+ * Vcc for our device is at 1.8V which puts it at 400 kHz,
+ * see Atmel AT24CM02 datasheet, section 8.3 DC Characteristics table, page 14.
+ *
+ * The procedure to disable the IP block is described in section
+ * 3.8.3 Disabling DW_apb_i2c on page 56.
+ */
+#define I2C_SPEED_MODE_FAST     2
+#define T_I2C_POLL_US           25
+#define I2C_MAX_T_POLL_COUNT    1000
 
-static void smu_v11_0_i2c_enable(struct i2c_adapter *control, bool enable)
+static int smu_v11_0_i2c_enable(struct i2c_adapter *control, bool enable)
 {
        struct amdgpu_device *adev = to_amdgpu_device(control);
 
        WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE, enable ? 1 : 0);
+
+       if (!enable) {
+               int ii;
+
+               for (ii = I2C_MAX_T_POLL_COUNT; ii > 0; ii--) {
+                       u32 en_stat = RREG32_SOC15(SMUIO,
+                                                  0,
+                                                  mmCKSVII2C_IC_ENABLE_STATUS);
+                       if (REG_GET_FIELD(en_stat, CKSVII2C_IC_ENABLE_STATUS, IC_EN))
+                               udelay(T_I2C_POLL_US);
+                       else
+                               return I2C_OK;
+               }
+
+               return I2C_ABORT;
+       }
+
+       return I2C_OK;
 }
 
 static void smu_v11_0_i2c_clear_status(struct i2c_adapter *control)
@@ -83,8 +117,13 @@ static void smu_v11_0_i2c_configure(struct i2c_adapter *control)
        reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_RESTART_EN, 1);
        reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_10BITADDR_MASTER, 0);
        reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_10BITADDR_SLAVE, 0);
-       /* Standard mode */
-       reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MAX_SPEED_MODE, 2);
+       /* The values of IC_MAX_SPEED_MODE are,
+        * 1: standard mode, 0 - 100 Kb/s,
+        * 2: fast mode, <= 400 Kb/s, or fast mode plus, <= 1000 Kb/s,
+        * 3: high speed mode, <= 3.4 Mb/s.
+        */
+       reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MAX_SPEED_MODE,
+                           I2C_SPEED_MODE_FAST);
        reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MASTER_MODE, 1);
 
        WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_CON, reg);
@@ -113,13 +152,15 @@ static void smu_v11_0_i2c_set_clock(struct i2c_adapter *control)
        WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_SDA_HOLD, 20);
 }
 
-static void smu_v11_0_i2c_set_address(struct i2c_adapter *control, uint8_t address)
+static void smu_v11_0_i2c_set_address(struct i2c_adapter *control, u16 address)
 {
        struct amdgpu_device *adev = to_amdgpu_device(control);
 
-       /* Convert fromr 8-bit to 7-bit address */
-       address >>= 1;
-       WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_TAR, (address & 0xFF));
+       /* The IC_TAR::IC_TAR field is 10-bits wide.
+        * It takes a 7-bit or 10-bit addresses as an address,
+        * i.e. no read/write bit--no wire format, just the address.
+        */
+       WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_TAR, address & 0x3FF);
 }
 
 static uint32_t smu_v11_0_i2c_poll_tx_status(struct i2c_adapter *control)
@@ -206,9 +247,6 @@ static uint32_t smu_v11_0_i2c_poll_rx_status(struct i2c_adapter *control)
        return ret;
 }
 
-
-
-
 /**
  * smu_v11_0_i2c_transmit - Send a block of data over the I2C bus to a slave device.
  *
@@ -221,17 +259,17 @@ static uint32_t smu_v11_0_i2c_poll_rx_status(struct i2c_adapter *control)
  * Returns 0 on success or error.
  */
 static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter *control,
-                                 uint8_t address, uint8_t *data,
-                                 uint32_t numbytes, uint32_t i2c_flag)
+                                      u16 address, u8 *data,
+                                      u32 numbytes, u32 i2c_flag)
 {
        struct amdgpu_device *adev = to_amdgpu_device(control);
-       uint32_t bytes_sent, reg, ret = 0;
+       u32 bytes_sent, reg, ret = I2C_OK;
        unsigned long  timeout_counter;
 
        bytes_sent = 0;
 
        DRM_DEBUG_DRIVER("I2C_Transmit(), address = %x, bytes = %d , data: ",
-                (uint16_t)address, numbytes);
+                        address, numbytes);
 
        if (drm_debug_enabled(DRM_UT_DRIVER)) {
                print_hex_dump(KERN_INFO, "data: ", DUMP_PREFIX_NONE,
@@ -246,53 +284,49 @@ static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter *control,
        /* Clear status bits */
        smu_v11_0_i2c_clear_status(control);
 
-
        timeout_counter = jiffies + msecs_to_jiffies(20);
 
        while (numbytes > 0) {
                reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS);
-               if (REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)) {
-                       do {
-                               reg = 0;
-                               /*
-                                * Prepare transaction, no need to set RESTART. I2C engine will send
-                                * START as soon as it sees data in TXFIFO
-                                */
-                               if (bytes_sent == 0)
-                                       reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, RESTART,
-                                                           (i2c_flag & I2C_RESTART) ? 1 : 0);
-                               reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, data[bytes_sent]);
-
-                               /* determine if we need to send STOP bit or not */
-                               if (numbytes == 1)
-                                       /* Final transaction, so send stop unless I2C_NO_STOP */
-                                       reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, STOP,
-                                                           (i2c_flag & I2C_NO_STOP) ? 0 : 1);
-                               /* Write */
-                               reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 0);
-                               WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg);
-
-                               /* Record that the bytes were transmitted */
-                               bytes_sent++;
-                               numbytes--;
-
-                               reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS);
-
-                       } while (numbytes &&  REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF));
-               }
-
-               /*
-                * We waited too long for the transmission FIFO to become not-full.
-                * Exit the loop with error.
-                */
-               if (time_after(jiffies, timeout_counter)) {
-                       ret |= I2C_SW_TIMEOUT;
-                       goto Err;
+               if (!REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)) {
+                       /*
+                        * We waited for too long for the transmission
+                        * FIFO to become not-full.  Exit the loop
+                        * with error.
+                        */
+                       if (time_after(jiffies, timeout_counter)) {
+                               ret |= I2C_SW_TIMEOUT;
+                               goto Err;
+                       }
+               } else {
+                       reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT,
+                                           data[bytes_sent]);
+
+                       /* Final message, final byte, must generate a
+                        * STOP to release the bus, i.e. don't hold
+                        * SCL low.
+                        */
+                       if (numbytes == 1 && i2c_flag & I2C_M_STOP)
+                               reg = REG_SET_FIELD(reg,
+                                                   CKSVII2C_IC_DATA_CMD,
+                                                   STOP, 1);
+
+                       if (bytes_sent == 0 && i2c_flag & I2C_X_RESTART)
+                               reg = REG_SET_FIELD(reg,
+                                                   CKSVII2C_IC_DATA_CMD,
+                                                   RESTART, 1);
+
+                       /* Write */
+                       reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 0);
+                       WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg);
+
+                       /* Record that the bytes were transmitted */
+                       bytes_sent++;
+                       numbytes--;
                }
        }
 
        ret = smu_v11_0_i2c_poll_tx_status(control);
-
 Err:
        /* Any error, no point in proceeding */
        if (ret != I2C_OK) {
@@ -323,8 +357,8 @@ Err:
  * Returns 0 on success or error.
  */
 static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter *control,
-                                uint8_t address, uint8_t *data,
-                                uint32_t numbytes, uint8_t i2c_flag)
+                                     u16 address, u8 *data,
+                                     u32 numbytes, u32 i2c_flag)
 {
        struct amdgpu_device *adev = to_amdgpu_device(control);
        uint32_t bytes_received, ret = I2C_OK;
@@ -342,23 +376,21 @@ static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter *control,
 
                smu_v11_0_i2c_clear_status(control);
 
-
                /* Prepare transaction */
-
-               /* Each time we disable I2C, so this is not a restart */
-               if (bytes_received == 0)
-                       reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, RESTART,
-                                           (i2c_flag & I2C_RESTART) ? 1 : 0);
-
                reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, 0);
                /* Read */
                reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 1);
 
-               /* Transmitting last byte */
-               if (numbytes == 1)
-                       /* Final transaction, so send stop if requested */
-                       reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, STOP,
-                                           (i2c_flag & I2C_NO_STOP) ? 0 : 1);
+               /* Final message, final byte, must generate a STOP
+                * to release the bus, i.e. don't hold SCL low.
+                */
+               if (numbytes == 1 && i2c_flag & I2C_M_STOP)
+                       reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD,
+                                           STOP, 1);
+
+               if (bytes_received == 0 && i2c_flag & I2C_X_RESTART)
+                       reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD,
+                                           RESTART, 1);
 
                WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg);
 
@@ -413,7 +445,6 @@ static void smu_v11_0_i2c_abort(struct i2c_adapter *control)
        DRM_DEBUG_DRIVER("I2C_Abort() Done.");
 }
 
-
 static bool smu_v11_0_i2c_activity_done(struct i2c_adapter *control)
 {
        struct amdgpu_device *adev = to_amdgpu_device(control);
@@ -425,7 +456,6 @@ static bool smu_v11_0_i2c_activity_done(struct i2c_adapter *control)
        reg_ic_enable_status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE_STATUS);
        reg_ic_enable = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE);
 
-
        if ((REG_GET_FIELD(reg_ic_enable, CKSVII2C_IC_ENABLE, ENABLE) == 0) &&
            (REG_GET_FIELD(reg_ic_enable_status, CKSVII2C_IC_ENABLE_STATUS, IC_EN) == 1)) {
                /*
@@ -455,6 +485,8 @@ static bool smu_v11_0_i2c_activity_done(struct i2c_adapter *control)
 
 static void smu_v11_0_i2c_init(struct i2c_adapter *control)
 {
+       int res;
+
        /* Disable clock gating */
        smu_v11_0_i2c_set_clock_gating(control, false);
 
@@ -462,7 +494,9 @@ static void smu_v11_0_i2c_init(struct i2c_adapter *control)
                DRM_WARN("I2C busy !");
 
        /* Disable I2C */
-       smu_v11_0_i2c_enable(control, false);
+       res = smu_v11_0_i2c_enable(control, false);
+       if (res != I2C_OK)
+               smu_v11_0_i2c_abort(control);
 
        /* Configure I2C to operate as master and in standard mode */
        smu_v11_0_i2c_configure(control);
@@ -475,21 +509,22 @@ static void smu_v11_0_i2c_init(struct i2c_adapter *control)
 static void smu_v11_0_i2c_fini(struct i2c_adapter *control)
 {
        struct amdgpu_device *adev = to_amdgpu_device(control);
-       uint32_t reg_ic_enable_status, reg_ic_enable;
+       u32 status, enable, en_stat;
+       int res;
 
-       smu_v11_0_i2c_enable(control, false);
+       res = smu_v11_0_i2c_enable(control, false);
+       if (res != I2C_OK) {
+               status  = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS);
+               enable  = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE);
+               en_stat = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE_STATUS);
 
-       /* Double check if disabled, else force abort */
-       reg_ic_enable_status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE_STATUS);
-       reg_ic_enable = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE);
-
-       if ((REG_GET_FIELD(reg_ic_enable, CKSVII2C_IC_ENABLE, ENABLE) == 0) &&
-           (REG_GET_FIELD(reg_ic_enable_status,
-                          CKSVII2C_IC_ENABLE_STATUS, IC_EN) == 1)) {
-               /*
-                * Nobody is using I2C engine, but engine remains active because
-                * someone missed to send STOP
+               /* Nobody is using the I2C engine, yet it remains
+                * active, possibly because someone missed to send
+                * STOP.
                 */
+               DRM_DEBUG_DRIVER("Aborting from fini: status:0x%08x "
+                                "enable:0x%08x enable_stat:0x%08x",
+                                status, enable, en_stat);
                smu_v11_0_i2c_abort(control);
        }
 
@@ -531,22 +566,12 @@ static bool smu_v11_0_i2c_bus_unlock(struct i2c_adapter *control)
 /***************************** I2C GLUE ****************************/
 
 static uint32_t smu_v11_0_i2c_read_data(struct i2c_adapter *control,
-                                       uint8_t address,
-                                       uint8_t *data,
-                                       uint32_t numbytes)
+                                       struct i2c_msg *msg, uint32_t i2c_flag)
 {
-       uint32_t  ret = 0;
-
-       /* First 2 bytes are dummy write to set EEPROM address */
-       ret = smu_v11_0_i2c_transmit(control, address, data, 2, I2C_NO_STOP);
-       if (ret != I2C_OK)
-               goto Fail;
+       uint32_t  ret;
 
-       /* Now read data starting with that address */
-       ret = smu_v11_0_i2c_receive(control, address, data + 2, numbytes - 2,
-                                   I2C_RESTART);
+       ret = smu_v11_0_i2c_receive(control, msg->addr, msg->buf, msg->len, i2c_flag);
 
-Fail:
        if (ret != I2C_OK)
                DRM_ERROR("ReadData() - I2C error occurred :%x", ret);
 
@@ -554,28 +579,15 @@ Fail:
 }
 
 static uint32_t smu_v11_0_i2c_write_data(struct i2c_adapter *control,
-                                        uint8_t address,
-                                        uint8_t *data,
-                                        uint32_t numbytes)
+                                       struct i2c_msg *msg, uint32_t i2c_flag)
 {
        uint32_t  ret;
 
-       ret = smu_v11_0_i2c_transmit(control, address, data, numbytes, 0);
+       ret = smu_v11_0_i2c_transmit(control, msg->addr, msg->buf, msg->len, i2c_flag);
 
        if (ret != I2C_OK)
                DRM_ERROR("WriteI2CData() - I2C error occurred :%x", ret);
-       else
-               /*
-                * According to EEPROM spec there is a MAX of 10 ms required for
-                * EEPROM to flush internal RX buffer after STOP was issued at the
-                * end of write transaction. During this time the EEPROM will not be
-                * responsive to any more commands - so wait a bit more.
-                *
-                * TODO Improve to wait for first ACK for slave address after
-                * internal write cycle done.
-                */
-               msleep(10);
-
+       
        return ret;
 
 }
@@ -584,12 +596,11 @@ static void lock_bus(struct i2c_adapter *i2c, unsigned int flags)
 {
        struct amdgpu_device *adev = to_amdgpu_device(i2c);
 
-       if (!smu_v11_0_i2c_bus_lock(i2c)) {
+       mutex_lock(&adev->pm.smu_i2c_mutex);
+       if (!smu_v11_0_i2c_bus_lock(i2c))
                DRM_ERROR("Failed to lock the bus from SMU");
-               return;
-       }
-
-       adev->pm.bus_locked = true;
+       else
+               adev->pm.bus_locked = true;
 }
 
 static int trylock_bus(struct i2c_adapter *i2c, unsigned int flags)
@@ -602,12 +613,11 @@ static void unlock_bus(struct i2c_adapter *i2c, unsigned int flags)
 {
        struct amdgpu_device *adev = to_amdgpu_device(i2c);
 
-       if (!smu_v11_0_i2c_bus_unlock(i2c)) {
+       if (!smu_v11_0_i2c_bus_unlock(i2c))
                DRM_ERROR("Failed to unlock the bus from SMU");
-               return;
-       }
-
-       adev->pm.bus_locked = false;
+       else
+               adev->pm.bus_locked = false;
+       mutex_unlock(&adev->pm.smu_i2c_mutex);
 }
 
 static const struct i2c_lock_operations smu_v11_0_i2c_i2c_lock_ops = {
@@ -617,27 +627,60 @@ static const struct i2c_lock_operations smu_v11_0_i2c_i2c_lock_ops = {
 };
 
 static int smu_v11_0_i2c_xfer(struct i2c_adapter *i2c_adap,
-                             struct i2c_msg *msgs, int num)
+                             struct i2c_msg *msg, int num)
 {
        int i, ret;
-       struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
-
-       if (!adev->pm.bus_locked) {
-               DRM_ERROR("I2C bus unlocked, stopping transaction!");
-               return -EIO;
-       }
+       u16 addr, dir;
 
        smu_v11_0_i2c_init(i2c_adap);
 
+       /* From the client's point of view, this sequence of
+        * messages-- the array i2c_msg *msg, is a single transaction
+        * on the bus, starting with START and ending with STOP.
+        *
+        * The client is welcome to send any sequence of messages in
+        * this array, as processing under this function here is
+        * striving to be agnostic.
+        *
+        * Record the first address and direction we see. If either
+        * changes for a subsequent message, generate ReSTART. The
+        * DW_apb_i2c databook, v1.21a, specifies that ReSTART is
+        * generated when the direction changes, with the default IP
+        * block parameter settings, but it doesn't specify if ReSTART
+        * is generated when the address changes (possibly...). We
+        * don't rely on the default IP block parameter settings as
+        * the block is shared and they may change.
+        */
+       if (num > 0) {
+               addr = msg[0].addr;
+               dir  = msg[0].flags & I2C_M_RD;
+       }
+
        for (i = 0; i < num; i++) {
-               if (msgs[i].flags & I2C_M_RD)
+               u32 i2c_flag = 0;
+
+               if (msg[i].addr != addr || (msg[i].flags ^ dir) & I2C_M_RD) {
+                       addr = msg[i].addr;
+                       dir  = msg[i].flags & I2C_M_RD;
+                       i2c_flag |= I2C_X_RESTART;
+               }
+
+               if (i == num - 1) {
+                       /* Set the STOP bit on the last message, so
+                        * that the IP block generates a STOP after
+                        * the last byte of the message.
+                        */
+                       i2c_flag |= I2C_M_STOP;
+               }
+
+               if (msg[i].flags & I2C_M_RD)
                        ret = smu_v11_0_i2c_read_data(i2c_adap,
-                                                     (uint8_t)msgs[i].addr,
-                                                     msgs[i].buf, msgs[i].len);
+                                                     msg + i,
+                                                     i2c_flag);
                else
                        ret = smu_v11_0_i2c_write_data(i2c_adap,
-                                                      (uint8_t)msgs[i].addr,
-                                                      msgs[i].buf, msgs[i].len);
+                                                      msg + i,
+                                                      i2c_flag);
 
                if (ret != I2C_OK) {
                        num = -EIO;
@@ -654,23 +697,28 @@ static u32 smu_v11_0_i2c_func(struct i2c_adapter *adap)
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-
 static const struct i2c_algorithm smu_v11_0_i2c_algo = {
        .master_xfer = smu_v11_0_i2c_xfer,
        .functionality = smu_v11_0_i2c_func,
 };
 
+static const struct i2c_adapter_quirks smu_v11_0_i2c_control_quirks = {
+       .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
 int smu_v11_0_i2c_control_init(struct i2c_adapter *control)
 {
        struct amdgpu_device *adev = to_amdgpu_device(control);
        int res;
 
+       mutex_init(&adev->pm.smu_i2c_mutex);
        control->owner = THIS_MODULE;
-       control->class = I2C_CLASS_SPD;
+       control->class = I2C_CLASS_HWMON;
        control->dev.parent = &adev->pdev->dev;
        control->algo = &smu_v11_0_i2c_algo;
        snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
        control->lock_ops = &smu_v11_0_i2c_i2c_lock_ops;
+       control->quirks = &smu_v11_0_i2c_control_quirks;
 
        res = i2c_add_adapter(control);
        if (res)
index b7d350be805020885d1f7bea3d1f9d5e39fbc2f0..a5e085e570f72ad6566662d13a83b7a1bf131f7f 100644 (file)
@@ -575,7 +575,7 @@ soc15_asic_reset_method(struct amdgpu_device *adev)
                baco_reset = amdgpu_dpm_is_baco_supported(adev);
                break;
        case CHIP_VEGA20:
-               if (adev->psp.sos_fw_version >= 0x80067)
+               if (adev->psp.sos.fw_version >= 0x80067)
                        baco_reset = amdgpu_dpm_is_baco_supported(adev);
 
                /*
@@ -635,7 +635,7 @@ static bool soc15_supports_baco(struct amdgpu_device *adev)
        case CHIP_ARCTURUS:
                return amdgpu_dpm_is_baco_supported(adev);
        case CHIP_VEGA20:
-               if (adev->psp.sos_fw_version >= 0x80067)
+               if (adev->psp.sos.fw_version >= 0x80067)
                        return amdgpu_dpm_is_baco_supported(adev);
                return false;
        default:
index 0eeb5e073be81f77bf9d3085d9924bb9fa7e2364..8a9ca87d86632b0e907030f70a23239d30aa128d 100644 (file)
 #define SOC15_REG_OFFSET(ip, inst, reg)        (adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg)
 
 #define __WREG32_SOC15_RLC__(reg, value, flag, hwip) \
-       ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->rlcg_wreg) ? \
-        adev->gfx.rlc.funcs->rlcg_wreg(adev, reg, value, flag, hwip) : \
+       ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->sriov_wreg) ? \
+        adev->gfx.rlc.funcs->sriov_wreg(adev, reg, value, flag, hwip) : \
         WREG32(reg, value))
 
 #define __RREG32_SOC15_RLC__(reg, flag, hwip) \
-       ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->rlcg_rreg) ? \
-        adev->gfx.rlc.funcs->rlcg_rreg(adev, reg, flag, hwip) : \
+       ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->sriov_rreg) ? \
+        adev->gfx.rlc.funcs->sriov_rreg(adev, reg, flag, hwip) : \
         RREG32(reg))
 
 #define WREG32_FIELD15(ip, idx, reg, field, val)       \
index ac2c27b7630c9fe91387afb4ab96d88331029bab..cce7127afeaade1503484bf705a1af87560e8bba 100644 (file)
@@ -33,7 +33,8 @@ enum ta_command_xgmi {
        TA_COMMAND_XGMI__GET_NODE_ID                    = 0x01,
        TA_COMMAND_XGMI__GET_HIVE_ID                    = 0x02,
        TA_COMMAND_XGMI__GET_GET_TOPOLOGY_INFO          = 0x03,
-       TA_COMMAND_XGMI__SET_TOPOLOGY_INFO              = 0x04
+       TA_COMMAND_XGMI__SET_TOPOLOGY_INFO              = 0x04,
+       TA_COMMAND_XGMI__GET_PEER_LINKS                 = 0x0B
 };
 
 /* XGMI related enumerations */
@@ -75,6 +76,11 @@ struct ta_xgmi_node_info {
        enum ta_xgmi_assigned_sdma_engine       sdma_engine;
 };
 
+struct ta_xgmi_peer_link_info {
+       uint64_t                                node_id;
+       uint8_t                                 num_links;
+};
+
 struct ta_xgmi_cmd_initialize_output {
        uint32_t        status;
 };
@@ -97,6 +103,11 @@ struct ta_xgmi_cmd_get_topology_info_output {
        struct ta_xgmi_node_info        nodes[TA_XGMI__MAX_CONNECTED_NODES];
 };
 
+struct ta_xgmi_cmd_get_peer_link_info_output {
+       uint32_t                        num_nodes;
+       struct ta_xgmi_peer_link_info   nodes[TA_XGMI__MAX_CONNECTED_NODES];
+};
+
 struct ta_xgmi_cmd_set_topology_info_input {
        uint32_t                        num_nodes;
        struct ta_xgmi_node_info        nodes[TA_XGMI__MAX_CONNECTED_NODES];
@@ -115,6 +126,7 @@ union ta_xgmi_cmd_output {
        struct ta_xgmi_cmd_get_node_id_output           get_node_id;
        struct ta_xgmi_cmd_get_hive_id_output           get_hive_id;
        struct ta_xgmi_cmd_get_topology_info_output     get_topology_info;
+       struct ta_xgmi_cmd_get_peer_link_info_output    get_link_info;
 };
 /**********************************************************/
 
index 3a8f787374c0ec3be959a90fd583ea7dc60a7b70..7da12110425cdfa19ec9a5612daf08d1f0777738 100644 (file)
 #include "umc/umc_6_7_0_offset.h"
 #include "umc/umc_6_7_0_sh_mask.h"
 
+const uint32_t
+       umc_v6_7_channel_idx_tbl_second[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM] = {
+               {28, 12, 6, 22},        {19, 3, 9, 25},
+               {20, 4, 30, 14},        {11, 27, 1, 17},
+               {24, 8, 2, 18},         {15, 31, 5, 21},
+               {16, 0, 26, 10},        {7, 23, 29, 13}
+};
+const uint32_t
+       umc_v6_7_channel_idx_tbl_first[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM] = {
+               {19, 3, 9, 25},         {28, 12, 6, 22},
+               {11, 27, 1, 17},        {20, 4, 30, 14},
+               {15, 31, 5, 21},        {24, 8, 2, 18},
+               {7, 23, 29, 13},        {16, 0, 26, 10}
+};
+
 static inline uint32_t get_umc_v6_7_reg_offset(struct amdgpu_device *adev,
                                              uint32_t umc_inst,
                                              uint32_t ch_inst)
index 4eb85f247e96c1eb42f4674bccfaa9a9005211ae..81b8f1844091e0abbd2ea7063a958bef496cd3f7 100644 (file)
@@ -23,6 +23,9 @@
 #ifndef __UMC_V6_7_H__
 #define __UMC_V6_7_H__
 
+#include "soc15_common.h"
+#include "amdgpu.h"
+
 /* EccErrCnt max value */
 #define UMC_V6_7_CE_CNT_MAX            0xffff
 /* umc ce interrupt threshold */
 
 #define UMC_V6_7_INST_DIST     0x40000
 
+/* number of umc channel instance with memory map register access */
+#define UMC_V6_7_CHANNEL_INSTANCE_NUM          4
+/* number of umc instance with memory map register access */
+#define UMC_V6_7_UMC_INSTANCE_NUM              8
+/* total channel instances in one umc block */
+#define UMC_V6_7_TOTAL_CHANNEL_NUM     (UMC_V6_7_CHANNEL_INSTANCE_NUM * UMC_V6_7_UMC_INSTANCE_NUM)
+/* UMC regiser per channel offset */
+#define UMC_V6_7_PER_CHANNEL_OFFSET            0x400
 extern const struct amdgpu_umc_ras_funcs umc_v6_7_ras_funcs;
+extern const uint32_t
+       umc_v6_7_channel_idx_tbl_second[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM];
+extern const uint32_t
+       umc_v6_7_channel_idx_tbl_first[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM];
 
 #endif
index 284bb42d6c866adbb8156fc36a7c4fb2cc5a8543..121ee9f2b8d16c66b6288489ad71e8019c423ec5 100644 (file)
@@ -119,7 +119,7 @@ static int vcn_v1_0_sw_init(void *handle)
                adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw;
                adev->firmware.fw_size +=
                        ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
-               DRM_INFO("PSP loading VCN firmware\n");
+               dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
        }
 
        r = amdgpu_vcn_resume(adev);
index 8af567c546dbc39b9f0ad533633e682d313f86de..f4686e918e0d1fd1117f02f33b8c199386501e24 100644 (file)
@@ -122,7 +122,7 @@ static int vcn_v2_0_sw_init(void *handle)
                adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw;
                adev->firmware.fw_size +=
                        ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
-               DRM_INFO("PSP loading VCN firmware\n");
+               dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
        }
 
        r = amdgpu_vcn_resume(adev);
index 888b17d84691ceb7ba6894be98cdfc288c5745e1..e0c0c3734432eac14aa715aa6ccf2760f3909f1e 100644 (file)
@@ -152,7 +152,7 @@ static int vcn_v2_5_sw_init(void *handle)
                        adev->firmware.fw_size +=
                                ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
                }
-               DRM_INFO("PSP loading VCN firmware\n");
+               dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
        }
 
        r = amdgpu_vcn_resume(adev);
index 47d4f04cbd69e1ca8918a01e53b5423fa1508bc5..2f017560948ebe7242977e33bd6a156d309faf4e 100644 (file)
@@ -160,7 +160,7 @@ static int vcn_v3_0_sw_init(void *handle)
                        adev->firmware.fw_size +=
                                ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
                }
-               DRM_INFO("PSP loading VCN firmware\n");
+               dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
        }
 
        r = amdgpu_vcn_resume(adev);
index c6b02aee4993e3551dfb9116d4a0a3b97314dd47..cfedfb1e8596c3346c9bf3019a18a52a846c9045 100644 (file)
@@ -1404,6 +1404,7 @@ static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev,
                break;
        case CHIP_NAVI10:
        case CHIP_NAVI12:
+       case CHIP_CYAN_SKILLFISH:
                pcache_info = navi10_cache_info;
                num_of_cache_types = ARRAY_SIZE(navi10_cache_info);
                break;
@@ -1989,8 +1990,19 @@ static int kfd_fill_gpu_direct_io_link_to_cpu(int *avail_size,
                sub_type_hdr->flags |= CRAT_IOLINK_FLAGS_BI_DIRECTIONAL;
                sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_XGMI;
                sub_type_hdr->num_hops_xgmi = 1;
+               if (adev->asic_type == CHIP_ALDEBARAN) {
+                       sub_type_hdr->minimum_bandwidth_mbs =
+                                       amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(
+                                                       kdev->kgd, NULL, true);
+                       sub_type_hdr->maximum_bandwidth_mbs =
+                                       sub_type_hdr->minimum_bandwidth_mbs;
+               }
        } else {
                sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_PCIEXPRESS;
+               sub_type_hdr->minimum_bandwidth_mbs =
+                               amdgpu_amdkfd_get_pcie_bandwidth_mbytes(kdev->kgd, true);
+               sub_type_hdr->maximum_bandwidth_mbs =
+                               amdgpu_amdkfd_get_pcie_bandwidth_mbytes(kdev->kgd, false);
        }
 
        sub_type_hdr->proximity_domain_from = proximity_domain;
@@ -2033,6 +2045,11 @@ static int kfd_fill_gpu_xgmi_link_to_gpu(int *avail_size,
        sub_type_hdr->proximity_domain_to = proximity_domain_to;
        sub_type_hdr->num_hops_xgmi =
                amdgpu_amdkfd_get_xgmi_hops_count(kdev->kgd, peer_kdev->kgd);
+       sub_type_hdr->maximum_bandwidth_mbs =
+               amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(kdev->kgd, peer_kdev->kgd, false);
+       sub_type_hdr->minimum_bandwidth_mbs = sub_type_hdr->maximum_bandwidth_mbs ?
+               amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(kdev->kgd, NULL, true) : 0;
+
        return 0;
 }
 
index 6b57dfd2cd2ac7a766f9bdab28ef184acc4a7f98..b551dd6750855388667fd42069513cfa4bf97322 100644 (file)
@@ -84,6 +84,7 @@ static const struct kfd2kgd_calls *kfd2kgd_funcs[] = {
        [CHIP_DIMGREY_CAVEFISH] = &gfx_v10_3_kfd2kgd,
        [CHIP_BEIGE_GOBY] = &gfx_v10_3_kfd2kgd,
        [CHIP_YELLOW_CARP] = &gfx_v10_3_kfd2kgd,
+       [CHIP_CYAN_SKILLFISH] = &gfx_v10_kfd2kgd,
 };
 
 #ifdef KFD_SUPPORT_IOMMU_V2
@@ -596,6 +597,24 @@ static const struct kfd_device_info yellow_carp_device_info = {
        .num_sdma_queues_per_engine = 2,
 };
 
+static const struct kfd_device_info cyan_skillfish_device_info = {
+       .asic_family = CHIP_CYAN_SKILLFISH,
+       .asic_name = "cyan_skillfish",
+       .max_pasid_bits = 16,
+       .max_no_of_hqd  = 24,
+       .doorbell_size  = 8,
+       .ih_ring_entry_size = 8 * sizeof(uint32_t),
+       .event_interrupt_class = &event_interrupt_class_v9,
+       .num_of_watch_points = 4,
+       .mqd_size_aligned = MQD_SIZE_ALIGNED,
+       .needs_iommu_device = false,
+       .supports_cwsr = true,
+       .needs_pci_atomics = true,
+       .num_sdma_engines = 2,
+       .num_xgmi_sdma_engines = 0,
+       .num_sdma_queues_per_engine = 8,
+};
+
 /* For each entry, [0] is regular and [1] is virtualisation device. */
 static const struct kfd_device_info *kfd_supported_devices[][2] = {
 #ifdef KFD_SUPPORT_IOMMU_V2
@@ -625,6 +644,7 @@ static const struct kfd_device_info *kfd_supported_devices[][2] = {
        [CHIP_DIMGREY_CAVEFISH] = {&dimgrey_cavefish_device_info, &dimgrey_cavefish_device_info},
        [CHIP_BEIGE_GOBY] = {&beige_goby_device_info, &beige_goby_device_info},
        [CHIP_YELLOW_CARP] = {&yellow_carp_device_info, NULL},
+       [CHIP_CYAN_SKILLFISH] = {&cyan_skillfish_device_info, NULL},
 };
 
 static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size,
@@ -1369,7 +1389,7 @@ void kfd_dec_compute_active(struct kfd_dev *kfd)
        WARN_ONCE(count < 0, "Compute profile ref. count error");
 }
 
-void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask)
+void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask)
 {
        if (kfd && kfd->init_complete)
                kfd_smi_event_update_thermal_throttling(kfd, throttle_bitmask);
@@ -1382,18 +1402,12 @@ void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask)
  */
 int kfd_debugfs_hang_hws(struct kfd_dev *dev)
 {
-       int r = 0;
-
        if (dev->dqm->sched_policy != KFD_SCHED_POLICY_HWS) {
                pr_err("HWS is not enabled");
                return -EINVAL;
        }
 
-       r = pm_debugfs_hang_hws(&dev->dqm->packets);
-       if (!r)
-               r = dqm_debugfs_execute_queues(dev->dqm);
-
-       return r;
+       return dqm_debugfs_hang_hws(dev->dqm);
 }
 
 #endif
index 16a1713808c2e7e6fd5639ec902337e282664882..a972ef5eae6883c8211dd86f2553e1d2be4409b7 100644 (file)
@@ -260,7 +260,7 @@ static int allocate_vmid(struct device_queue_manager *dqm,
 static int flush_texture_cache_nocpsch(struct kfd_dev *kdev,
                                struct qcm_process_device *qpd)
 {
-       const struct packet_manager_funcs *pmf = qpd->dqm->packets.pmf;
+       const struct packet_manager_funcs *pmf = qpd->dqm->packet_mgr.pmf;
        int ret;
 
        if (!qpd->ib_kaddr)
@@ -1000,7 +1000,7 @@ static int start_nocpsch(struct device_queue_manager *dqm)
        init_interrupts(dqm);
        
        if (dqm->dev->device_info->asic_family == CHIP_HAWAII)
-               return pm_init(&dqm->packets, dqm);
+               return pm_init(&dqm->packet_mgr, dqm);
        dqm->sched_running = true;
 
        return 0;
@@ -1009,7 +1009,7 @@ static int start_nocpsch(struct device_queue_manager *dqm)
 static int stop_nocpsch(struct device_queue_manager *dqm)
 {
        if (dqm->dev->device_info->asic_family == CHIP_HAWAII)
-               pm_uninit(&dqm->packets, false);
+               pm_uninit(&dqm->packet_mgr, false);
        dqm->sched_running = false;
 
        return 0;
@@ -1124,7 +1124,7 @@ static int set_sched_resources(struct device_queue_manager *dqm)
                        "queue mask: 0x%8llX\n",
                        res.vmid_mask, res.queue_mask);
 
-       return pm_send_set_resources(&dqm->packets, &res);
+       return pm_send_set_resources(&dqm->packet_mgr, &res);
 }
 
 static int initialize_cpsch(struct device_queue_manager *dqm)
@@ -1164,7 +1164,8 @@ static int start_cpsch(struct device_queue_manager *dqm)
 
        retval = 0;
 
-       retval = pm_init(&dqm->packets, dqm);
+       dqm_lock(dqm);
+       retval = pm_init(&dqm->packet_mgr, dqm);
        if (retval)
                goto fail_packet_manager_init;
 
@@ -1186,7 +1187,6 @@ static int start_cpsch(struct device_queue_manager *dqm)
 
        init_interrupts(dqm);
 
-       dqm_lock(dqm);
        /* clear hang status when driver try to start the hw scheduler */
        dqm->is_hws_hang = false;
        dqm->is_resetting = false;
@@ -1197,8 +1197,9 @@ static int start_cpsch(struct device_queue_manager *dqm)
        return 0;
 fail_allocate_vidmem:
 fail_set_sched_resources:
-       pm_uninit(&dqm->packets, false);
+       pm_uninit(&dqm->packet_mgr, false);
 fail_packet_manager_init:
+       dqm_unlock(dqm);
        return retval;
 }
 
@@ -1211,12 +1212,12 @@ static int stop_cpsch(struct device_queue_manager *dqm)
                unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0);
        hanging = dqm->is_hws_hang || dqm->is_resetting;
        dqm->sched_running = false;
-       dqm_unlock(dqm);
 
-       pm_release_ib(&dqm->packets);
+       pm_release_ib(&dqm->packet_mgr);
 
        kfd_gtt_sa_free(dqm->dev, dqm->fence_mem);
-       pm_uninit(&dqm->packets, hanging);
+       pm_uninit(&dqm->packet_mgr, hanging);
+       dqm_unlock(dqm);
 
        return 0;
 }
@@ -1390,7 +1391,7 @@ static int map_queues_cpsch(struct device_queue_manager *dqm)
        if (dqm->active_runlist)
                return 0;
 
-       retval = pm_send_runlist(&dqm->packets, &dqm->queues);
+       retval = pm_send_runlist(&dqm->packet_mgr, &dqm->queues);
        pr_debug("%s sent runlist\n", __func__);
        if (retval) {
                pr_err("failed to execute runlist\n");
@@ -1416,13 +1417,13 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
        if (!dqm->active_runlist)
                return retval;
 
-       retval = pm_send_unmap_queue(&dqm->packets, KFD_QUEUE_TYPE_COMPUTE,
+       retval = pm_send_unmap_queue(&dqm->packet_mgr, KFD_QUEUE_TYPE_COMPUTE,
                        filter, filter_param, false, 0);
        if (retval)
                return retval;
 
        *dqm->fence_addr = KFD_FENCE_INIT;
-       pm_send_query_status(&dqm->packets, dqm->fence_gpu_addr,
+       pm_send_query_status(&dqm->packet_mgr, dqm->fence_gpu_addr,
                                KFD_FENCE_COMPLETED);
        /* should be timed out */
        retval = amdkfd_fence_wait_timeout(dqm->fence_addr, KFD_FENCE_COMPLETED,
@@ -1448,14 +1449,14 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
         * check those fields
         */
        mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ];
-       if (mqd_mgr->read_doorbell_id(dqm->packets.priv_queue->queue->mqd)) {
+       if (mqd_mgr->read_doorbell_id(dqm->packet_mgr.priv_queue->queue->mqd)) {
                pr_err("HIQ MQD's queue_doorbell_id0 is not 0, Queue preemption time out\n");
                while (halt_if_hws_hang)
                        schedule();
                return -ETIME;
        }
 
-       pm_release_ib(&dqm->packets);
+       pm_release_ib(&dqm->packet_mgr);
        dqm->active_runlist = false;
 
        return retval;
@@ -1946,6 +1947,7 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev)
        case CHIP_DIMGREY_CAVEFISH:
        case CHIP_BEIGE_GOBY:
        case CHIP_YELLOW_CARP:
+       case CHIP_CYAN_SKILLFISH:
                device_queue_manager_init_v10_navi10(&dqm->asic_ops);
                break;
        default:
@@ -2099,11 +2101,16 @@ int dqm_debugfs_hqds(struct seq_file *m, void *data)
        return r;
 }
 
-int dqm_debugfs_execute_queues(struct device_queue_manager *dqm)
+int dqm_debugfs_hang_hws(struct device_queue_manager *dqm)
 {
        int r = 0;
 
        dqm_lock(dqm);
+       r = pm_debugfs_hang_hws(&dqm->packet_mgr);
+       if (r) {
+               dqm_unlock(dqm);
+               return r;
+       }
        dqm->active_runlist = true;
        r = execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0);
        dqm_unlock(dqm);
index 71e2fde56b2b7a2d4c745b6bfaae7d49818c3c77..c8719682c4da071567f107bc6fcac642eef81c54 100644 (file)
@@ -169,7 +169,7 @@ struct device_queue_manager {
        struct device_queue_manager_asic_ops asic_ops;
 
        struct mqd_manager      *mqd_mgrs[KFD_MQD_TYPE_MAX];
-       struct packet_manager   packets;
+       struct packet_manager   packet_mgr;
        struct kfd_dev          *dev;
        struct mutex            lock_hidden; /* use dqm_lock/unlock(dqm) */
        struct list_head        queues;
index a9b329f0f86203849081adea333b7bc84eae066f..2e86692def19a598ccdd03ef8d143b7b3da64369 100644 (file)
@@ -422,6 +422,7 @@ int kfd_init_apertures(struct kfd_process *process)
                        case CHIP_DIMGREY_CAVEFISH:
                        case CHIP_BEIGE_GOBY:
                        case CHIP_YELLOW_CARP:
+                       case CHIP_CYAN_SKILLFISH:
                                kfd_init_apertures_v9(pdd, id);
                                break;
                        default:
index d8e940f03102e3f0148257bcde568969e2a12f22..e547f1f8c49f601bfbd1b2b56395c4d7d711a9ab 100644 (file)
@@ -251,6 +251,7 @@ int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm)
        case CHIP_DIMGREY_CAVEFISH:
        case CHIP_BEIGE_GOBY:
        case CHIP_YELLOW_CARP:
+       case CHIP_CYAN_SKILLFISH:
                pm->pmf = &kfd_v9_pm_funcs;
                break;
        case CHIP_ALDEBARAN:
@@ -278,6 +279,7 @@ void pm_uninit(struct packet_manager *pm, bool hanging)
 {
        mutex_destroy(&pm->lock);
        kernel_queue_uninit(pm->priv_queue, hanging);
+       pm->priv_queue = NULL;
 }
 
 int pm_send_set_resources(struct packet_manager *pm,
@@ -447,6 +449,9 @@ int pm_debugfs_hang_hws(struct packet_manager *pm)
        uint32_t *buffer, size;
        int r = 0;
 
+       if (!pm->priv_queue)
+               return -EAGAIN;
+
        size = pm->pmf->query_status_size;
        mutex_lock(&pm->lock);
        kq_acquire_packet_buffer(pm->priv_queue,
index 3426743ed228beca2178d162197bc05f03676c14..8a5dfda224bfa14dc20b8e5e73ab11d48ed05b55 100644 (file)
@@ -1194,7 +1194,7 @@ int pm_debugfs_runlist(struct seq_file *m, void *data);
 
 int kfd_debugfs_hang_hws(struct kfd_dev *dev);
 int pm_debugfs_hang_hws(struct packet_manager *pm);
-int dqm_debugfs_execute_queues(struct device_queue_manager *dqm);
+int dqm_debugfs_hang_hws(struct device_queue_manager *dqm);
 
 #else
 
index 2465224235593ce8660f78375941148541ab9565..ed4bc5f844ce7675f17937515fbb24d085482b23 100644 (file)
@@ -205,23 +205,23 @@ void kfd_smi_event_update_gpu_reset(struct kfd_dev *dev, bool post_reset)
 }
 
 void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev,
-                                            uint32_t throttle_bitmask)
+                                            uint64_t throttle_bitmask)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)dev->kgd;
        /*
         * ThermalThrottle msg = throttle_bitmask(8):
         *                       thermal_interrupt_count(16):
-        * 1 byte event + 1 byte space + 8 byte throttle_bitmask +
+        * 1 byte event + 1 byte space + 16 byte throttle_bitmask +
         * 1 byte : + 16 byte thermal_interupt_counter + 1 byte \n +
-        * 1 byte \0 = 29
+        * 1 byte \0 = 37
         */
-       char fifo_in[29];
+       char fifo_in[37];
        int len;
 
        if (list_empty(&dev->smi_clients))
                return;
 
-       len = snprintf(fifo_in, sizeof(fifo_in), "%x %x:%llx\n",
+       len = snprintf(fifo_in, sizeof(fifo_in), "%x %llx:%llx\n",
                       KFD_SMI_EVENT_THERMAL_THROTTLE, throttle_bitmask,
                       atomic64_read(&adev->smu.throttle_int_counter));
 
index b9b0438202e21cf92ac6a71e11c3e0da9f2d02b3..bffd0c32b0603c14ee6be0169bc44749600206ac 100644 (file)
@@ -26,7 +26,7 @@
 int kfd_smi_event_open(struct kfd_dev *dev, uint32_t *fd);
 void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid);
 void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev,
-                                            uint32_t throttle_bitmask);
+                                            uint64_t throttle_bitmask);
 void kfd_smi_event_update_gpu_reset(struct kfd_dev *dev, bool post_reset);
 
 #endif
index b1ce072aa20bb5b6cddbc5505e44ffe5fcbd2167..ef992dd2da3afb45113e0c0d04f386346fbf1489 100644 (file)
@@ -1424,6 +1424,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
        case CHIP_DIMGREY_CAVEFISH:
        case CHIP_BEIGE_GOBY:
        case CHIP_YELLOW_CARP:
+       case CHIP_CYAN_SKILLFISH:
                dev->node_props.capability |= ((HSA_CAP_DOORBELL_TYPE_2_0 <<
                        HSA_CAP_DOORBELL_TYPE_TOTALBITS_SHIFT) &
                        HSA_CAP_DOORBELL_TYPE_TOTALBITS_MASK);
@@ -1630,7 +1631,7 @@ int kfd_debugfs_rls_by_device(struct seq_file *m, void *data)
                }
 
                seq_printf(m, "Node %u, gpu_id %x:\n", i++, dev->gpu->id);
-               r = pm_debugfs_runlist(m, &dev->gpu->dqm->packets);
+               r = pm_debugfs_runlist(m, &dev->gpu->dqm->packet_mgr);
                if (r)
                        break;
        }
index d3a2a5ff57e951e15cf36b3d46344a79f62a6355..986c9d29d6864aba72080f245c35196b498b5f79 100644 (file)
@@ -618,6 +618,7 @@ static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params)
 }
 #endif
 
+#define DMUB_TRACE_MAX_READ 64
 /**
  * dm_dmub_outbox1_low_irq() - Handles Outbox interrupt
  * @interrupt_params: used for determining the Outbox instance
@@ -625,7 +626,6 @@ static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params)
  * Handles the Outbox Interrupt
  * event handler.
  */
-#define DMUB_TRACE_MAX_READ 64
 static void dm_dmub_outbox1_low_irq(void *interrupt_params)
 {
        struct dmub_notification notify;
@@ -2412,6 +2412,7 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
        static const u8 pre_computed_values[] = {
                50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69,
                71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98};
+       int i;
 
        if (!aconnector || !aconnector->dc_link)
                return;
@@ -2423,15 +2424,21 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
        conn_base = &aconnector->base;
        adev = drm_to_adev(conn_base->dev);
        dm = &adev->dm;
-       caps = &dm->backlight_caps;
+       for (i = 0; i < dm->num_of_edps; i++) {
+               if (link == dm->backlight_link[i])
+                       break;
+       }
+       if (i >= dm->num_of_edps)
+               return;
+       caps = &dm->backlight_caps[i];
        caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
        caps->aux_support = false;
        max_cll = conn_base->hdr_sink_metadata.hdmi_type1.max_cll;
        min_cll = conn_base->hdr_sink_metadata.hdmi_type1.min_cll;
 
-       if (caps->ext_caps->bits.oled == 1 ||
+       if (caps->ext_caps->bits.oled == 1 /*||
            caps->ext_caps->bits.sdr_aux_backlight_control == 1 ||
-           caps->ext_caps->bits.hdr_aux_backlight_control == 1)
+           caps->ext_caps->bits.hdr_aux_backlight_control == 1*/)
                caps->aux_support = true;
 
        if (amdgpu_backlight == 0)
@@ -3423,35 +3430,36 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
 #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
        defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
 
-static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm)
+static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm,
+                                           int bl_idx)
 {
 #if defined(CONFIG_ACPI)
        struct amdgpu_dm_backlight_caps caps;
 
        memset(&caps, 0, sizeof(caps));
 
-       if (dm->backlight_caps.caps_valid)
+       if (dm->backlight_caps[bl_idx].caps_valid)
                return;
 
        amdgpu_acpi_get_backlight_caps(&caps);
        if (caps.caps_valid) {
-               dm->backlight_caps.caps_valid = true;
+               dm->backlight_caps[bl_idx].caps_valid = true;
                if (caps.aux_support)
                        return;
-               dm->backlight_caps.min_input_signal = caps.min_input_signal;
-               dm->backlight_caps.max_input_signal = caps.max_input_signal;
+               dm->backlight_caps[bl_idx].min_input_signal = caps.min_input_signal;
+               dm->backlight_caps[bl_idx].max_input_signal = caps.max_input_signal;
        } else {
-               dm->backlight_caps.min_input_signal =
+               dm->backlight_caps[bl_idx].min_input_signal =
                                AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
-               dm->backlight_caps.max_input_signal =
+               dm->backlight_caps[bl_idx].max_input_signal =
                                AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
        }
 #else
-       if (dm->backlight_caps.aux_support)
+       if (dm->backlight_caps[bl_idx].aux_support)
                return;
 
-       dm->backlight_caps.min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
-       dm->backlight_caps.max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
+       dm->backlight_caps[bl_idx].min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
+       dm->backlight_caps[bl_idx].max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
 #endif
 }
 
@@ -3502,41 +3510,31 @@ static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *cap
 }
 
 static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
+                                        int bl_idx,
                                         u32 user_brightness)
 {
        struct amdgpu_dm_backlight_caps caps;
-       struct dc_link *link[AMDGPU_DM_MAX_NUM_EDP];
-       u32 brightness[AMDGPU_DM_MAX_NUM_EDP];
+       struct dc_link *link;
+       u32 brightness;
        bool rc;
-       int i;
 
-       amdgpu_dm_update_backlight_caps(dm);
-       caps = dm->backlight_caps;
+       amdgpu_dm_update_backlight_caps(dm, bl_idx);
+       caps = dm->backlight_caps[bl_idx];
 
-       for (i = 0; i < dm->num_of_edps; i++) {
-               dm->brightness[i] = user_brightness;
-               brightness[i] = convert_brightness_from_user(&caps, dm->brightness[i]);
-               link[i] = (struct dc_link *)dm->backlight_link[i];
-       }
+       dm->brightness[bl_idx] = user_brightness;
+       brightness = convert_brightness_from_user(&caps, dm->brightness[bl_idx]);
+       link = (struct dc_link *)dm->backlight_link[bl_idx];
 
        /* Change brightness based on AUX property */
        if (caps.aux_support) {
-               for (i = 0; i < dm->num_of_edps; i++) {
-                       rc = dc_link_set_backlight_level_nits(link[i], true, brightness[i],
-                               AUX_BL_DEFAULT_TRANSITION_TIME_MS);
-                       if (!rc) {
-                               DRM_DEBUG("DM: Failed to update backlight via AUX on eDP[%d]\n", i);
-                               break;
-                       }
-               }
+               rc = dc_link_set_backlight_level_nits(link, true, brightness,
+                                                     AUX_BL_DEFAULT_TRANSITION_TIME_MS);
+               if (!rc)
+                       DRM_DEBUG("DM: Failed to update backlight via AUX on eDP[%d]\n", bl_idx);
        } else {
-               for (i = 0; i < dm->num_of_edps; i++) {
-                       rc = dc_link_set_backlight_level(dm->backlight_link[i], brightness[i], 0);
-                       if (!rc) {
-                               DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", i);
-                               break;
-                       }
-               }
+               rc = dc_link_set_backlight_level(link, brightness, 0);
+               if (!rc)
+                       DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", bl_idx);
        }
 
        return rc ? 0 : 1;
@@ -3545,33 +3543,41 @@ static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
 static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
 {
        struct amdgpu_display_manager *dm = bl_get_data(bd);
+       int i;
 
-       amdgpu_dm_backlight_set_level(dm, bd->props.brightness);
+       for (i = 0; i < dm->num_of_edps; i++) {
+               if (bd == dm->backlight_dev[i])
+                       break;
+       }
+       if (i >= AMDGPU_DM_MAX_NUM_EDP)
+               i = 0;
+       amdgpu_dm_backlight_set_level(dm, i, bd->props.brightness);
 
        return 0;
 }
 
-static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm)
+static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm,
+                                        int bl_idx)
 {
        struct amdgpu_dm_backlight_caps caps;
+       struct dc_link *link = (struct dc_link *)dm->backlight_link[bl_idx];
 
-       amdgpu_dm_update_backlight_caps(dm);
-       caps = dm->backlight_caps;
+       amdgpu_dm_update_backlight_caps(dm, bl_idx);
+       caps = dm->backlight_caps[bl_idx];
 
        if (caps.aux_support) {
-               struct dc_link *link = (struct dc_link *)dm->backlight_link[0];
                u32 avg, peak;
                bool rc;
 
                rc = dc_link_get_backlight_level_nits(link, &avg, &peak);
                if (!rc)
-                       return dm->brightness[0];
+                       return dm->brightness[bl_idx];
                return convert_brightness_to_user(&caps, avg);
        } else {
-               int ret = dc_link_get_backlight_level(dm->backlight_link[0]);
+               int ret = dc_link_get_backlight_level(link);
 
                if (ret == DC_ERROR_UNEXPECTED)
-                       return dm->brightness[0];
+                       return dm->brightness[bl_idx];
                return convert_brightness_to_user(&caps, ret);
        }
 }
@@ -3579,8 +3585,15 @@ static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm)
 static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
 {
        struct amdgpu_display_manager *dm = bl_get_data(bd);
+       int i;
 
-       return amdgpu_dm_backlight_get_level(dm);
+       for (i = 0; i < dm->num_of_edps; i++) {
+               if (bd == dm->backlight_dev[i])
+                       break;
+       }
+       if (i >= AMDGPU_DM_MAX_NUM_EDP)
+               i = 0;
+       return amdgpu_dm_backlight_get_level(dm, i);
 }
 
 static const struct backlight_ops amdgpu_dm_backlight_ops = {
@@ -3594,31 +3607,28 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm)
 {
        char bl_name[16];
        struct backlight_properties props = { 0 };
-       int i;
 
-       amdgpu_dm_update_backlight_caps(dm);
-       for (i = 0; i < dm->num_of_edps; i++)
-               dm->brightness[i] = AMDGPU_MAX_BL_LEVEL;
+       amdgpu_dm_update_backlight_caps(dm, dm->num_of_edps);
+       dm->brightness[dm->num_of_edps] = AMDGPU_MAX_BL_LEVEL;
 
        props.max_brightness = AMDGPU_MAX_BL_LEVEL;
        props.brightness = AMDGPU_MAX_BL_LEVEL;
        props.type = BACKLIGHT_RAW;
 
        snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",
-                adev_to_drm(dm->adev)->primary->index);
+                adev_to_drm(dm->adev)->primary->index + dm->num_of_edps);
 
-       dm->backlight_dev = backlight_device_register(bl_name,
-                                                     adev_to_drm(dm->adev)->dev,
-                                                     dm,
-                                                     &amdgpu_dm_backlight_ops,
-                                                     &props);
+       dm->backlight_dev[dm->num_of_edps] = backlight_device_register(bl_name,
+                                                                      adev_to_drm(dm->adev)->dev,
+                                                                      dm,
+                                                                      &amdgpu_dm_backlight_ops,
+                                                                      &props);
 
-       if (IS_ERR(dm->backlight_dev))
+       if (IS_ERR(dm->backlight_dev[dm->num_of_edps]))
                DRM_ERROR("DM: Backlight registration failed!\n");
        else
                DRM_DEBUG_DRIVER("DM: Registered Backlight device: %s\n", bl_name);
 }
-
 #endif
 
 static int initialize_plane(struct amdgpu_display_manager *dm,
@@ -3675,10 +3685,10 @@ static void register_backlight_device(struct amdgpu_display_manager *dm,
                 * DM initialization because not having a backlight control
                 * is better then a black screen.
                 */
-               if (!dm->backlight_dev)
+               if (!dm->backlight_dev[dm->num_of_edps])
                        amdgpu_dm_register_backlight_device(dm);
 
-               if (dm->backlight_dev) {
+               if (dm->backlight_dev[dm->num_of_edps]) {
                        dm->backlight_link[dm->num_of_edps] = link;
                        dm->num_of_edps++;
                }
@@ -4747,7 +4757,7 @@ fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev,
                                          const bool force_disable_dcc)
 {
        const uint64_t modifier = afb->base.modifier;
-       int ret;
+       int ret = 0;
 
        fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier);
        tiling_info->gfx9.swizzle = modifier_gfx9_swizzle_mode(modifier);
@@ -4765,9 +4775,9 @@ fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev,
 
        ret = validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size);
        if (ret)
-               return ret;
+               drm_dbg_kms(adev_to_drm(adev), "validate_dcc: returned error: %d\n", ret);
 
-       return 0;
+       return ret;
 }
 
 static int
@@ -6198,6 +6208,7 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
        const struct dc_link *link = aconnector->dc_link;
        struct amdgpu_device *adev = drm_to_adev(connector->dev);
        struct amdgpu_display_manager *dm = &adev->dm;
+       int i;
 
        /*
         * Call only if mst_mgr was iniitalized before since it's not done
@@ -6208,12 +6219,11 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
 
 #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
        defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
-
-       if ((link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) &&
-           link->type != dc_connection_none &&
-           dm->backlight_dev) {
-               backlight_device_unregister(dm->backlight_dev);
-               dm->backlight_dev = NULL;
+       for (i = 0; i < dm->num_of_edps; i++) {
+               if ((link == dm->backlight_link[i]) && dm->backlight_dev[i]) {
+                       backlight_device_unregister(dm->backlight_dev[i]);
+                       dm->backlight_dev[i] = NULL;
+               }
        }
 #endif
 
@@ -7570,8 +7580,10 @@ static uint add_fs_modes(struct amdgpu_dm_connector *aconnector)
         * 60       - Commonly used
         * 48,72,96 - Multiples of 24
         */
-       const uint32_t common_rates[] = { 23976, 24000, 25000, 29970, 30000,
-                                        48000, 50000, 60000, 72000, 96000 };
+       static const uint32_t common_rates[] = {
+               23976, 24000, 25000, 29970, 30000,
+               48000, 50000, 60000, 72000, 96000
+       };
 
        /*
         * Find mode with highest refresh rate with the same resolution
@@ -9191,8 +9203,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
 #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||          \
        defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
        /* restore the backlight level */
-       if (dm->backlight_dev && (amdgpu_dm_backlight_get_level(dm) != dm->brightness[0]))
-               amdgpu_dm_backlight_set_level(dm, dm->brightness[0]);
+       for (i = 0; i < dm->num_of_edps; i++) {
+               if (dm->backlight_dev[i] &&
+                   (amdgpu_dm_backlight_get_level(dm, i) != dm->brightness[i]))
+                       amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]);
+       }
 #endif
        /*
         * send vblank event on all events not handled in flip and
@@ -10549,13 +10564,68 @@ static bool is_dp_capable_without_timing_msa(struct dc *dc,
        return capable;
 }
 
-static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
+static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm,
+               unsigned int offset,
+               unsigned int total_length,
+               uint8_t *data,
+               unsigned int length,
+               struct amdgpu_hdmi_vsdb_info *vsdb)
+{
+       bool res;
+       union dmub_rb_cmd cmd;
+       struct dmub_cmd_send_edid_cea *input;
+       struct dmub_cmd_edid_cea_output *output;
+
+       if (length > DMUB_EDID_CEA_DATA_CHUNK_BYTES)
+               return false;
+
+       memset(&cmd, 0, sizeof(cmd));
+
+       input = &cmd.edid_cea.data.input;
+
+       cmd.edid_cea.header.type = DMUB_CMD__EDID_CEA;
+       cmd.edid_cea.header.sub_type = 0;
+       cmd.edid_cea.header.payload_bytes =
+               sizeof(cmd.edid_cea) - sizeof(cmd.edid_cea.header);
+       input->offset = offset;
+       input->length = length;
+       input->total_length = total_length;
+       memcpy(input->payload, data, length);
+
+       res = dc_dmub_srv_cmd_with_reply_data(dm->dc->ctx->dmub_srv, &cmd);
+       if (!res) {
+               DRM_ERROR("EDID CEA parser failed\n");
+               return false;
+       }
+
+       output = &cmd.edid_cea.data.output;
+
+       if (output->type == DMUB_CMD__EDID_CEA_ACK) {
+               if (!output->ack.success) {
+                       DRM_ERROR("EDID CEA ack failed at offset %d\n",
+                                       output->ack.offset);
+               }
+       } else if (output->type == DMUB_CMD__EDID_CEA_AMD_VSDB) {
+               if (!output->amd_vsdb.vsdb_found)
+                       return false;
+
+               vsdb->freesync_supported = output->amd_vsdb.freesync_supported;
+               vsdb->amd_vsdb_version = output->amd_vsdb.amd_vsdb_version;
+               vsdb->min_refresh_rate_hz = output->amd_vsdb.min_frame_rate;
+               vsdb->max_refresh_rate_hz = output->amd_vsdb.max_frame_rate;
+       } else {
+               DRM_WARN("Unknown EDID CEA parser results\n");
+               return false;
+       }
+
+       return true;
+}
+
+static bool parse_edid_cea_dmcu(struct amdgpu_display_manager *dm,
                uint8_t *edid_ext, int len,
                struct amdgpu_hdmi_vsdb_info *vsdb_info)
 {
        int i;
-       struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);
-       struct dc *dc = adev->dm.dc;
 
        /* send extension block to DMCU for parsing */
        for (i = 0; i < len; i += 8) {
@@ -10563,14 +10633,14 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
                int offset;
 
                /* send 8 bytes a time */
-               if (!dc_edid_parser_send_cea(dc, i, len, &edid_ext[i], 8))
+               if (!dc_edid_parser_send_cea(dm->dc, i, len, &edid_ext[i], 8))
                        return false;
 
                if (i+8 == len) {
                        /* EDID block sent completed, expect result */
                        int version, min_rate, max_rate;
 
-                       res = dc_edid_parser_recv_amd_vsdb(dc, &version, &min_rate, &max_rate);
+                       res = dc_edid_parser_recv_amd_vsdb(dm->dc, &version, &min_rate, &max_rate);
                        if (res) {
                                /* amd vsdb found */
                                vsdb_info->freesync_supported = 1;
@@ -10584,7 +10654,7 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
                }
 
                /* check for ack*/
-               res = dc_edid_parser_recv_cea_ack(dc, &offset);
+               res = dc_edid_parser_recv_cea_ack(dm->dc, &offset);
                if (!res)
                        return false;
        }
@@ -10592,6 +10662,34 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
        return false;
 }
 
+static bool parse_edid_cea_dmub(struct amdgpu_display_manager *dm,
+               uint8_t *edid_ext, int len,
+               struct amdgpu_hdmi_vsdb_info *vsdb_info)
+{
+       int i;
+
+       /* send extension block to DMCU for parsing */
+       for (i = 0; i < len; i += 8) {
+               /* send 8 bytes a time */
+               if (!dm_edid_parser_send_cea(dm, i, len, &edid_ext[i], 8, vsdb_info))
+                       return false;
+       }
+
+       return vsdb_info->freesync_supported;
+}
+
+static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
+               uint8_t *edid_ext, int len,
+               struct amdgpu_hdmi_vsdb_info *vsdb_info)
+{
+       struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);
+
+       if (adev->dm.dmub_srv)
+               return parse_edid_cea_dmub(&adev->dm, edid_ext, len, vsdb_info);
+       else
+               return parse_edid_cea_dmcu(&adev->dm, edid_ext, len, vsdb_info);
+}
+
 static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
                struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info)
 {
index 9522d4ca299efb8d4e473883992b436087e74f26..ab1670b16b02f2625b430d84558246acdf5fb74b 100644 (file)
@@ -365,13 +365,13 @@ struct amdgpu_display_manager {
 
        spinlock_t irq_handler_list_table_lock;
 
-       struct backlight_device *backlight_dev;
+       struct backlight_device *backlight_dev[AMDGPU_DM_MAX_NUM_EDP];
 
        const struct dc_link *backlight_link[AMDGPU_DM_MAX_NUM_EDP];
 
        uint8_t num_of_edps;
 
-       struct amdgpu_dm_backlight_caps backlight_caps;
+       struct amdgpu_dm_backlight_caps backlight_caps[AMDGPU_DM_MAX_NUM_EDP];
 
        struct mod_freesync *freesync_module;
 #ifdef CONFIG_DRM_AMD_DC_HDCP
index f1145086a46882c9ae4ba693cfd1e59393d433de..87daa78a32b8bd4071a3ebdc59476abefc4074d0 100644 (file)
@@ -197,29 +197,29 @@ static ssize_t dp_link_settings_read(struct file *f, char __user *buf,
 
        rd_buf_ptr = rd_buf;
 
-       str_len = strlen("Current:  %d  %d  %d  ");
-       snprintf(rd_buf_ptr, str_len, "Current:  %d  %d  %d  ",
+       str_len = strlen("Current:  %d  0x%x  %d  ");
+       snprintf(rd_buf_ptr, str_len, "Current:  %d  0x%x  %d  ",
                        link->cur_link_settings.lane_count,
                        link->cur_link_settings.link_rate,
                        link->cur_link_settings.link_spread);
        rd_buf_ptr += str_len;
 
-       str_len = strlen("Verified:  %d  %d  %d  ");
-       snprintf(rd_buf_ptr, str_len, "Verified:  %d  %d  %d  ",
+       str_len = strlen("Verified:  %d  0x%x  %d  ");
+       snprintf(rd_buf_ptr, str_len, "Verified:  %d  0x%x  %d  ",
                        link->verified_link_cap.lane_count,
                        link->verified_link_cap.link_rate,
                        link->verified_link_cap.link_spread);
        rd_buf_ptr += str_len;
 
-       str_len = strlen("Reported:  %d  %d  %d  ");
-       snprintf(rd_buf_ptr, str_len, "Reported:  %d  %d  %d  ",
+       str_len = strlen("Reported:  %d  0x%x  %d  ");
+       snprintf(rd_buf_ptr, str_len, "Reported:  %d  0x%x  %d  ",
                        link->reported_link_cap.lane_count,
                        link->reported_link_cap.link_rate,
                        link->reported_link_cap.link_spread);
        rd_buf_ptr += str_len;
 
-       str_len = strlen("Preferred:  %d  %d  %d  ");
-       snprintf(rd_buf_ptr, str_len, "Preferred:  %d  %d  %d\n",
+       str_len = strlen("Preferred:  %d  0x%x  %d  ");
+       snprintf(rd_buf_ptr, str_len, "Preferred:  %d  0x%x  %d\n",
                        link->preferred_link_setting.lane_count,
                        link->preferred_link_setting.link_rate,
                        link->preferred_link_setting.link_spread);
@@ -377,7 +377,7 @@ static ssize_t dp_phy_settings_read(struct file *f, char __user *buf,
        if (!rd_buf)
                return -EINVAL;
 
-       snprintf(rd_buf, rd_buf_size, "  %d  %d  %d  ",
+       snprintf(rd_buf, rd_buf_size, "  %d  %d  %d\n",
                        link->cur_lane_setting.VOLTAGE_SWING,
                        link->cur_lane_setting.PRE_EMPHASIS,
                        link->cur_lane_setting.POST_CURSOR2);
index e63c6885c7576aeaf9bdec810ab238df3690c7be..8e39e9245d063b9bb47e75873d5e40e5c6d97a33 100644 (file)
@@ -655,10 +655,8 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct
                INIT_DELAYED_WORK(&hdcp_work[i].property_validate_dwork, event_property_validate);
 
                hdcp_work[i].hdcp.config.psp.handle = &adev->psp;
-               if (dc->ctx->dce_version == DCN_VERSION_3_1) {
+               if (dc->ctx->dce_version == DCN_VERSION_3_1)
                        hdcp_work[i].hdcp.config.psp.caps.dtm_v3_supported = 1;
-                       hdcp_work[i].hdcp.config.psp.caps.opm_state_query_supported = false;
-               }
                hdcp_work[i].hdcp.config.ddc.handle = dc_get_link_at_index(dc, i);
                hdcp_work[i].hdcp.config.ddc.funcs.write_i2c = lp_write_i2c;
                hdcp_work[i].hdcp.config.ddc.funcs.read_i2c = lp_read_i2c;
index e133edc587d318098e5576acbff9f30584f8fe68..76ec8ec92efdd7b0baa2df14030be0048f2a8ff9 100644 (file)
@@ -264,9 +264,9 @@ static void rv1_update_clocks(struct clk_mgr *clk_mgr_base,
                if (pp_smu->set_hard_min_fclk_by_freq &&
                                pp_smu->set_hard_min_dcfclk_by_freq &&
                                pp_smu->set_min_deep_sleep_dcfclk) {
-                       pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, new_clocks->fclk_khz / 1000);
-                       pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, new_clocks->dcfclk_khz / 1000);
-                       pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, (new_clocks->dcfclk_deep_sleep_khz + 999) / 1000);
+                       pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->fclk_khz));
+                       pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->dcfclk_khz));
+                       pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->dcfclk_deep_sleep_khz));
                }
        }
 
@@ -284,9 +284,9 @@ static void rv1_update_clocks(struct clk_mgr *clk_mgr_base,
                if (pp_smu->set_hard_min_fclk_by_freq &&
                                pp_smu->set_hard_min_dcfclk_by_freq &&
                                pp_smu->set_min_deep_sleep_dcfclk) {
-                       pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, new_clocks->fclk_khz / 1000);
-                       pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, new_clocks->dcfclk_khz / 1000);
-                       pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, (new_clocks->dcfclk_deep_sleep_khz + 999) / 1000);
+                       pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->fclk_khz));
+                       pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->dcfclk_khz));
+                       pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->dcfclk_deep_sleep_khz));
                }
        }
 }
index dbc7cde00433f5fcb1ef6261e3813ccd4cfd3fe6..fe18bb9e19aa56bf86731b6bdde229344e22e04c 100644 (file)
@@ -130,7 +130,7 @@ int rv1_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_di
        actual_dispclk_set_mhz = rv1_vbios_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetDispclkFreq,
-                       requested_dispclk_khz / 1000);
+                       khz_to_mhz_ceil(requested_dispclk_khz));
 
        if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
                if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
@@ -150,7 +150,7 @@ int rv1_vbios_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
        actual_dprefclk_set_mhz = rv1_vbios_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetDprefclkFreq,
-                       clk_mgr->base.dprefclk_khz / 1000);
+                       khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz));
 
        /* TODO: add code for programing DP DTO, currently this is down by command table */
 
index 6e0c5c664fdc5da6ab18b4a7859b06139b425559..0d01aa9f15a62e3a8dc3e3a9e96236d3680d62df 100644 (file)
@@ -197,7 +197,7 @@ void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr, struct
 
        REG_UPDATE(DENTIST_DISPCLK_CNTL,
                        DENTIST_DISPCLK_WDIVIDER, dispclk_wdivider);
-//     REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 5, 100);
+       REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 1000);
        REG_UPDATE(DENTIST_DISPCLK_CNTL,
                        DENTIST_DPPCLK_WDIVIDER, dppclk_wdivider);
        REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_CHG_DONE, 1, 5, 100);
@@ -253,20 +253,20 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base,
        if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) {
                clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz;
                if (pp_smu && pp_smu->set_hard_min_dcfclk_by_freq)
-                       pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, clk_mgr_base->clks.dcfclk_khz / 1000);
+                       pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_khz));
        }
 
        if (should_set_clock(safe_to_lower,
                        new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) {
                clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
                if (pp_smu && pp_smu->set_min_deep_sleep_dcfclk)
-                       pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, clk_mgr_base->clks.dcfclk_deep_sleep_khz / 1000);
+                       pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_deep_sleep_khz));
        }
 
        if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr_base->clks.socclk_khz)) {
                clk_mgr_base->clks.socclk_khz = new_clocks->socclk_khz;
                if (pp_smu && pp_smu->set_hard_min_socclk_by_freq)
-                       pp_smu->set_hard_min_socclk_by_freq(&pp_smu->pp_smu, clk_mgr_base->clks.socclk_khz / 1000);
+                       pp_smu->set_hard_min_socclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(clk_mgr_base->clks.socclk_khz));
        }
 
        total_plane_count = clk_mgr_helper_get_active_plane_cnt(dc, context);
@@ -281,7 +281,7 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base,
        if (should_set_clock(safe_to_lower, new_clocks->dramclk_khz, clk_mgr_base->clks.dramclk_khz)) {
                clk_mgr_base->clks.dramclk_khz = new_clocks->dramclk_khz;
                if (pp_smu && pp_smu->set_hard_min_uclk_by_freq)
-                       pp_smu->set_hard_min_uclk_by_freq(&pp_smu->pp_smu, clk_mgr_base->clks.dramclk_khz / 1000);
+                       pp_smu->set_hard_min_uclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
        }
 
        if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
@@ -306,7 +306,7 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base,
 
                clk_mgr_base->clks.disp_dpp_voltage_level_khz = new_clocks->disp_dpp_voltage_level_khz;
                if (pp_smu && pp_smu->set_voltage_by_freq)
-                       pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_DISPCLK, clk_mgr_base->clks.disp_dpp_voltage_level_khz / 1000);
+                       pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_DISPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.disp_dpp_voltage_level_khz));
        }
 
        if (dc->config.forced_clocks == false || (force_reset && safe_to_lower)) {
@@ -502,7 +502,7 @@ static void dcn2_notify_link_rate_change(struct clk_mgr *clk_mgr_base, struct dc
 
        if (max_phyclk_req != clk_mgr_base->clks.phyclk_khz) {
                clk_mgr_base->clks.phyclk_khz = max_phyclk_req;
-               pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_PHYCLK, clk_mgr_base->clks.phyclk_khz / 1000);
+               pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_PHYCLK, khz_to_mhz_ceil(clk_mgr_base->clks.phyclk_khz));
        }
 }
 
index 7deeec9d1c7c785498051368b5423fef7877c77e..9f7eed6688c4b5d662ccf153e1907e23f236d773 100644 (file)
@@ -126,7 +126,7 @@ int rn_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dis
        actual_dispclk_set_mhz = rn_vbios_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetDispclkFreq,
-                       requested_dispclk_khz / 1000);
+                       khz_to_mhz_ceil(requested_dispclk_khz));
 
        if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
                if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
@@ -138,7 +138,7 @@ int rn_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dis
 
        // pmfw always set clock more than or equal requested clock
        if (!IS_DIAG_DC(dc->ctx->dce_environment))
-               ASSERT(actual_dispclk_set_mhz >= requested_dispclk_khz / 1000);
+               ASSERT(actual_dispclk_set_mhz >= khz_to_mhz_ceil(requested_dispclk_khz));
 
        return actual_dispclk_set_mhz * 1000;
 }
@@ -150,7 +150,7 @@ int rn_vbios_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
        actual_dprefclk_set_mhz = rn_vbios_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetDprefclkFreq,
-                       clk_mgr->base.dprefclk_khz / 1000);
+                       khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz));
 
        /* TODO: add code for programing DP DTO, currently this is down by command table */
 
@@ -167,7 +167,7 @@ int rn_vbios_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int reque
        actual_dcfclk_set_mhz = rn_vbios_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetHardMinDcfclkByFreq,
-                       requested_dcfclk_khz / 1000);
+                       khz_to_mhz_ceil(requested_dcfclk_khz));
 
        return actual_dcfclk_set_mhz * 1000;
 }
@@ -182,7 +182,7 @@ int rn_vbios_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int
        actual_min_ds_dcfclk_mhz = rn_vbios_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetMinDeepSleepDcfclk,
-                       requested_min_ds_dcfclk_khz / 1000);
+                       khz_to_mhz_ceil(requested_min_ds_dcfclk_khz));
 
        return actual_min_ds_dcfclk_mhz * 1000;
 }
@@ -192,7 +192,7 @@ void rn_vbios_smu_set_phyclk(struct clk_mgr_internal *clk_mgr, int requested_phy
        rn_vbios_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetPhyclkVoltageByFreq,
-                       requested_phyclk_khz / 1000);
+                       khz_to_mhz_ceil(requested_phyclk_khz));
 }
 
 int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz)
@@ -203,10 +203,10 @@ int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_
        actual_dppclk_set_mhz = rn_vbios_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetDppclkFreq,
-                       requested_dpp_khz / 1000);
+                       khz_to_mhz_ceil(requested_dpp_khz));
 
        if (!IS_DIAG_DC(dc->ctx->dce_environment))
-               ASSERT(actual_dppclk_set_mhz >= requested_dpp_khz / 1000);
+               ASSERT(actual_dppclk_set_mhz >= khz_to_mhz_ceil(requested_dpp_khz));
 
        return actual_dppclk_set_mhz * 1000;
 }
index af7004b770aeb9ae3c6265ad2272b04e9bf14983..1861a147a7fa1f31e17dcc28e1b067c5dfa0f7c4 100644 (file)
@@ -284,12 +284,12 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base,
 
        if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) {
                clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz;
-               dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DCEFCLK, clk_mgr_base->clks.dcfclk_khz / 1000);
+               dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DCEFCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_khz));
        }
 
        if (should_set_clock(safe_to_lower, new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) {
                clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
-               dcn30_smu_set_min_deep_sleep_dcef_clk(clk_mgr, clk_mgr_base->clks.dcfclk_deep_sleep_khz / 1000);
+               dcn30_smu_set_min_deep_sleep_dcef_clk(clk_mgr, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_deep_sleep_khz));
        }
 
        if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr_base->clks.socclk_khz))
@@ -317,20 +317,20 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base,
        /* set UCLK to requested value if P-State switching is supported, or to re-enable P-State switching */
        if (clk_mgr_base->clks.p_state_change_support &&
                        (update_uclk || !clk_mgr_base->clks.prev_p_state_change_support))
-               dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, clk_mgr_base->clks.dramclk_khz / 1000);
+               dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
 
        if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr_base->clks.dppclk_khz)) {
                if (clk_mgr_base->clks.dppclk_khz > new_clocks->dppclk_khz)
                        dpp_clock_lowered = true;
 
                clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz;
-               dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_PIXCLK, clk_mgr_base->clks.dppclk_khz / 1000);
+               dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_PIXCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dppclk_khz));
                update_dppclk = true;
        }
 
        if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
                clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
-               dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, clk_mgr_base->clks.dispclk_khz / 1000);
+               dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dispclk_khz));
                update_dispclk = true;
        }
 
@@ -396,12 +396,17 @@ static void dcn3_set_hard_min_memclk(struct clk_mgr *clk_mgr_base, bool current_
        if (!clk_mgr->smu_present)
                return;
 
-       if (current_mode)
-               dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
-                               clk_mgr_base->clks.dramclk_khz / 1000);
-       else
+       if (current_mode) {
+               if (clk_mgr_base->clks.p_state_change_support)
+                       dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
+                                       khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
+               else
+                       dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
+                                       clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries - 1].memclk_mhz);
+       } else {
                dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
                                clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz);
+       }
 }
 
 /* Set max memclk to highest DPM value */
@@ -489,7 +494,7 @@ static void dcn30_notify_link_rate_change(struct clk_mgr *clk_mgr_base, struct d
 
        if (max_phyclk_req != clk_mgr_base->clks.phyclk_khz) {
                clk_mgr_base->clks.phyclk_khz = max_phyclk_req;
-               dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_PHYCLK, clk_mgr_base->clks.phyclk_khz / 1000);
+               dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_PHYCLK, khz_to_mhz_ceil(clk_mgr_base->clks.phyclk_khz));
        }
 }
 
index 07774fa2c2cfa2c9f6277e7f2192cce87010c5b1..6ea64261585474dd40dcec28fd770e4de0dab6c9 100644 (file)
@@ -133,7 +133,7 @@ int dcn301_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispc
        actual_dispclk_set_mhz = dcn301_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetDispclkFreq,
-                       requested_dispclk_khz / 1000);
+                       khz_to_mhz_ceil(requested_dispclk_khz));
 
        return actual_dispclk_set_mhz * 1000;
 }
@@ -147,7 +147,7 @@ int dcn301_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
        actual_dprefclk_set_mhz = dcn301_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetDprefclkFreq,
-                       clk_mgr->base.dprefclk_khz / 1000);
+                       khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz));
 
        /* TODO: add code for programing DP DTO, currently this is down by command table */
 
@@ -163,7 +163,7 @@ int dcn301_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int request
        actual_dcfclk_set_mhz = dcn301_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetHardMinDcfclkByFreq,
-                       requested_dcfclk_khz / 1000);
+                       khz_to_mhz_ceil(requested_dcfclk_khz));
 
        return actual_dcfclk_set_mhz * 1000;
 }
@@ -177,7 +177,7 @@ int dcn301_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int r
        actual_min_ds_dcfclk_mhz = dcn301_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetMinDeepSleepDcfclk,
-                       requested_min_ds_dcfclk_khz / 1000);
+                       khz_to_mhz_ceil(requested_min_ds_dcfclk_khz));
 
        return actual_min_ds_dcfclk_mhz * 1000;
 }
@@ -191,7 +191,7 @@ int dcn301_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_kh
        actual_dppclk_set_mhz = dcn301_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetDppclkFreq,
-                       requested_dpp_khz / 1000);
+                       khz_to_mhz_ceil(requested_dpp_khz));
 
        return actual_dppclk_set_mhz * 1000;
 }
index c636b589d69db3c696cc7d6c347c808993122fb4..7046da14bb2a5b9fa90c20cde90d7051467d3e93 100644 (file)
@@ -114,7 +114,7 @@ void vg_update_clocks(struct clk_mgr *clk_mgr_base,
 
                        display_count = vg_get_active_display_cnt_wa(dc, context);
                        /* if we can go lower, go lower */
-                       if (display_count == 0) {
+                       if (display_count == 0 && !IS_DIAG_DC(dc->ctx->dce_environment)) {
                                union display_idle_optimization_u idle_info = { 0 };
 
                                idle_info.idle_info.df_request_disabled = 1;
index dad4a4c18bcf37746f3a04de1ba470ce42e7ae0d..8c2b77eb94593a50c83b37a061371651b08e72aa 100644 (file)
@@ -147,7 +147,7 @@ int dcn31_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispcl
        actual_dispclk_set_mhz = dcn31_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetDispclkFreq,
-                       (requested_dispclk_khz + 999) / 1000);
+                       khz_to_mhz_ceil(requested_dispclk_khz));
 
        return actual_dispclk_set_mhz * 1000;
 }
@@ -162,7 +162,7 @@ int dcn31_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
        actual_dprefclk_set_mhz = dcn31_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetDprefclkFreq,
-                       (clk_mgr->base.dprefclk_khz + 999) / 1000);
+                       khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz));
 
        /* TODO: add code for programing DP DTO, currently this is down by command table */
 
@@ -182,7 +182,7 @@ int dcn31_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requeste
        actual_dcfclk_set_mhz = dcn31_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetHardMinDcfclkByFreq,
-                       (requested_dcfclk_khz + 999) / 1000);
+                       khz_to_mhz_ceil(requested_dcfclk_khz));
 
        return actual_dcfclk_set_mhz * 1000;
 }
@@ -200,7 +200,7 @@ int dcn31_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int re
        actual_min_ds_dcfclk_mhz = dcn31_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetMinDeepSleepDcfclk,
-                       (requested_min_ds_dcfclk_khz + 999) / 1000);
+                       khz_to_mhz_ceil(requested_min_ds_dcfclk_khz));
 
        return actual_min_ds_dcfclk_mhz * 1000;
 }
@@ -215,7 +215,7 @@ int dcn31_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz
        actual_dppclk_set_mhz = dcn31_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetDppclkFreq,
-                       (requested_dpp_khz + 999) / 1000);
+                       khz_to_mhz_ceil(requested_dpp_khz));
 
        return actual_dppclk_set_mhz * 1000;
 }
index 6132b645bfd19ae1c76a0c13daf8bf0c2acdeff5..8bd7f42a8053fc21067c4f116e2e702feab2874c 100644 (file)
@@ -541,6 +541,7 @@ static void link_disconnect_sink(struct dc_link *link)
        }
 
        link->dpcd_sink_count = 0;
+       //link->dpcd_caps.dpcd_rev.raw = 0;
 }
 
 static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *link)
@@ -742,6 +743,7 @@ static bool detect_dp(struct dc_link *link,
                                                                sink_caps,
                                                                audio_support);
                link->dpcd_caps.dongle_type = sink_caps->dongle_type;
+               link->dpcd_caps.dpcd_rev.raw = 0;
        }
 
        return true;
@@ -1663,6 +1665,12 @@ struct dc_link *link_create(const struct link_init_data *init_params)
        if (false == dc_link_construct(link, init_params))
                goto construct_fail;
 
+       /*
+        * Must use preferred_link_setting, not reported_link_cap or verified_link_cap,
+        * since struct preferred_link_setting won't be reset after S3.
+        */
+       link->preferred_link_setting.dpcd_source_device_specific_field_support = true;
+
        return link;
 
 construct_fail:
@@ -3509,61 +3517,6 @@ void dc_link_enable_hpd_filter(struct dc_link *link, bool enable)
        }
 }
 
-uint32_t dc_bandwidth_in_kbps_from_timing(
-       const struct dc_crtc_timing *timing)
-{
-       uint32_t bits_per_channel = 0;
-       uint32_t kbps;
-
-#if defined(CONFIG_DRM_AMD_DC_DCN)
-       if (timing->flags.DSC)
-               return dc_dsc_stream_bandwidth_in_kbps(timing,
-                               timing->dsc_cfg.bits_per_pixel,
-                               timing->dsc_cfg.num_slices_h,
-                               timing->dsc_cfg.is_dp);
-#endif
-
-       switch (timing->display_color_depth) {
-       case COLOR_DEPTH_666:
-               bits_per_channel = 6;
-               break;
-       case COLOR_DEPTH_888:
-               bits_per_channel = 8;
-               break;
-       case COLOR_DEPTH_101010:
-               bits_per_channel = 10;
-               break;
-       case COLOR_DEPTH_121212:
-               bits_per_channel = 12;
-               break;
-       case COLOR_DEPTH_141414:
-               bits_per_channel = 14;
-               break;
-       case COLOR_DEPTH_161616:
-               bits_per_channel = 16;
-               break;
-       default:
-               ASSERT(bits_per_channel != 0);
-               bits_per_channel = 8;
-               break;
-       }
-
-       kbps = timing->pix_clk_100hz / 10;
-       kbps *= bits_per_channel;
-
-       if (timing->flags.Y_ONLY != 1) {
-               /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/
-               kbps *= 3;
-               if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
-                       kbps /= 2;
-               else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
-                       kbps = kbps * 2 / 3;
-       }
-
-       return kbps;
-
-}
-
 void dc_link_set_drive_settings(struct dc *dc,
                                struct link_training_settings *lt_settings,
                                const struct dc_link *link)
@@ -3769,3 +3722,58 @@ bool dc_link_should_enable_fec(const struct dc_link *link)
 
        return ret;
 }
+
+uint32_t dc_bandwidth_in_kbps_from_timing(
+               const struct dc_crtc_timing *timing)
+{
+       uint32_t bits_per_channel = 0;
+       uint32_t kbps;
+
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+       if (timing->flags.DSC)
+               return dc_dsc_stream_bandwidth_in_kbps(timing,
+                               timing->dsc_cfg.bits_per_pixel,
+                               timing->dsc_cfg.num_slices_h,
+                               timing->dsc_cfg.is_dp);
+#endif
+
+       switch (timing->display_color_depth) {
+       case COLOR_DEPTH_666:
+               bits_per_channel = 6;
+               break;
+       case COLOR_DEPTH_888:
+               bits_per_channel = 8;
+               break;
+       case COLOR_DEPTH_101010:
+               bits_per_channel = 10;
+               break;
+       case COLOR_DEPTH_121212:
+               bits_per_channel = 12;
+               break;
+       case COLOR_DEPTH_141414:
+               bits_per_channel = 14;
+               break;
+       case COLOR_DEPTH_161616:
+               bits_per_channel = 16;
+               break;
+       default:
+               ASSERT(bits_per_channel != 0);
+               bits_per_channel = 8;
+               break;
+       }
+
+       kbps = timing->pix_clk_100hz / 10;
+       kbps *= bits_per_channel;
+
+       if (timing->flags.Y_ONLY != 1) {
+               /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/
+               kbps *= 3;
+               if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
+                       kbps /= 2;
+               else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
+                       kbps = kbps * 2 / 3;
+       }
+
+       return kbps;
+
+}
index 9fb8c46dc606981aa4711a0b51862cc0e1389a1b..f56e061d35bce31c20038eaf12f223fcba6a031d 100644 (file)
@@ -1241,29 +1241,15 @@ enum link_training_result dp_check_link_loss_status(
 static inline void decide_8b_10b_training_settings(
         struct dc_link *link,
        const struct dc_link_settings *link_setting,
-       const struct dc_link_training_overrides *overrides,
        struct link_training_settings *lt_settings)
 {
-       uint32_t lane;
-
        memset(lt_settings, '\0', sizeof(struct link_training_settings));
 
        /* Initialize link settings */
        lt_settings->link_settings.use_link_rate_set = link_setting->use_link_rate_set;
        lt_settings->link_settings.link_rate_set = link_setting->link_rate_set;
-
-       if (link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN)
-               lt_settings->link_settings.link_rate = link->preferred_link_setting.link_rate;
-       else
-               lt_settings->link_settings.link_rate = link_setting->link_rate;
-
-       if (link->preferred_link_setting.lane_count != LANE_COUNT_UNKNOWN)
-               lt_settings->link_settings.lane_count = link->preferred_link_setting.lane_count;
-       else
-               lt_settings->link_settings.lane_count = link_setting->lane_count;
-
-       /*@todo[vdevulap] move SS to LS, should not be handled by displaypath*/
-
+       lt_settings->link_settings.link_rate = link_setting->link_rate;
+       lt_settings->link_settings.lane_count = link_setting->lane_count;
        /* TODO hard coded to SS for now
         * lt_settings.link_settings.link_spread =
         * dal_display_path_is_ss_supported(
@@ -1271,30 +1257,52 @@ static inline void decide_8b_10b_training_settings(
         * LINK_SPREAD_05_DOWNSPREAD_30KHZ :
         * LINK_SPREAD_DISABLED;
         */
-       /* Initialize link spread */
-       if (link->dp_ss_off)
-               lt_settings->link_settings.link_spread = LINK_SPREAD_DISABLED;
-       else if (overrides->downspread != NULL)
-               lt_settings->link_settings.link_spread
-                       = *overrides->downspread
-                       ? LINK_SPREAD_05_DOWNSPREAD_30KHZ
-                       : LINK_SPREAD_DISABLED;
-       else
-               lt_settings->link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ;
-
+       lt_settings->link_settings.link_spread = link->dp_ss_off ?
+                       LINK_SPREAD_DISABLED : LINK_SPREAD_05_DOWNSPREAD_30KHZ;
        lt_settings->lttpr_mode = link->lttpr_mode;
+       lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting);
+       lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting);
+       lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting);
+       lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting);
+       lt_settings->enhanced_framing = 1;
+       lt_settings->should_set_fec_ready = true;
+}
+
+void dp_decide_training_settings(
+               struct dc_link *link,
+               const struct dc_link_settings *link_settings,
+               struct link_training_settings *lt_settings)
+{
+       if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING)
+               decide_8b_10b_training_settings(link, link_settings, lt_settings);
+}
+
+static void override_training_settings(
+               struct dc_link *link,
+               const struct dc_link_training_overrides *overrides,
+               struct link_training_settings *lt_settings)
+{
+       uint32_t lane;
+
+       /* Override link settings */
+       if (link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN)
+               lt_settings->link_settings.link_rate = link->preferred_link_setting.link_rate;
+       if (link->preferred_link_setting.lane_count != LANE_COUNT_UNKNOWN)
+               lt_settings->link_settings.lane_count = link->preferred_link_setting.lane_count;
+
+       /* Override link spread */
+       if (!link->dp_ss_off && overrides->downspread != NULL)
+               lt_settings->link_settings.link_spread = *overrides->downspread ?
+                               LINK_SPREAD_05_DOWNSPREAD_30KHZ
+                               : LINK_SPREAD_DISABLED;
 
-       /* Initialize lane settings overrides */
+       /* Override lane settings */
        if (overrides->voltage_swing != NULL)
                lt_settings->voltage_swing = overrides->voltage_swing;
-
        if (overrides->pre_emphasis != NULL)
                lt_settings->pre_emphasis = overrides->pre_emphasis;
-
        if (overrides->post_cursor2 != NULL)
                lt_settings->post_cursor2 = overrides->post_cursor2;
-
-       /* Initialize lane settings (VS/PE/PC2) */
        for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
                lt_settings->lane_settings[lane].VOLTAGE_SWING =
                        lt_settings->voltage_swing != NULL ?
@@ -1313,45 +1321,22 @@ static inline void decide_8b_10b_training_settings(
        /* Initialize training timings */
        if (overrides->cr_pattern_time != NULL)
                lt_settings->cr_pattern_time = *overrides->cr_pattern_time;
-       else
-               lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting);
 
        if (overrides->eq_pattern_time != NULL)
                lt_settings->eq_pattern_time = *overrides->eq_pattern_time;
-       else
-               lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting);
 
        if (overrides->pattern_for_cr != NULL)
                lt_settings->pattern_for_cr = *overrides->pattern_for_cr;
-       else
-               lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting);
        if (overrides->pattern_for_eq != NULL)
                lt_settings->pattern_for_eq = *overrides->pattern_for_eq;
-       else
-               lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting);
 
        if (overrides->enhanced_framing != NULL)
                lt_settings->enhanced_framing = *overrides->enhanced_framing;
-       else
-               lt_settings->enhanced_framing = 1;
 
        if (link->preferred_training_settings.fec_enable != NULL)
                lt_settings->should_set_fec_ready = *link->preferred_training_settings.fec_enable;
-       else
-               lt_settings->should_set_fec_ready = true;
-}
-
-void dp_decide_training_settings(
-               struct dc_link *link,
-               const struct dc_link_settings *link_settings,
-               const struct dc_link_training_overrides *overrides,
-               struct link_training_settings *lt_settings)
-{
-       if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING)
-               decide_8b_10b_training_settings(link, link_settings, overrides, lt_settings);
 }
 
-
 uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count)
 {
        switch (lttpr_repeater_count) {
@@ -1581,6 +1566,9 @@ bool dc_link_dp_perform_link_training_skip_aux(
        dp_decide_training_settings(
                        link,
                        link_setting,
+                       &lt_settings);
+       override_training_settings(
+                       link,
                        &link->preferred_training_settings,
                        &lt_settings);
 
@@ -1727,6 +1715,9 @@ enum link_training_result dc_link_dp_perform_link_training(
        dp_decide_training_settings(
                        link,
                        link_settings,
+                       &lt_settings);
+       override_training_settings(
+                       link,
                        &link->preferred_training_settings,
                        &lt_settings);
 
@@ -1939,11 +1930,13 @@ enum link_training_result dc_link_dp_sync_lt_attempt(
        bool fec_enable = false;
 
        dp_decide_training_settings(
-               link,
-               link_settings,
-               lt_overrides,
-               &lt_settings);
-
+                       link,
+                       link_settings,
+                       &lt_settings);
+       override_training_settings(
+                       link,
+                       lt_overrides,
+                       &lt_settings);
        /* Setup MST Mode */
        if (lt_overrides->mst_enable)
                set_dp_mst_mode(link, *lt_overrides->mst_enable);
@@ -4793,10 +4786,18 @@ void dpcd_set_source_specific_data(struct dc_link *link)
 
                        uint8_t hblank_size = (uint8_t)link->dc->caps.min_horizontal_blanking_period;
 
-                       result_write_min_hblank = core_link_write_dpcd(link,
-                               DP_SOURCE_MINIMUM_HBLANK_SUPPORTED, (uint8_t *)(&hblank_size),
-                               sizeof(hblank_size));
+                       if (link->preferred_link_setting.dpcd_source_device_specific_field_support) {
+                               result_write_min_hblank = core_link_write_dpcd(link,
+                                       DP_SOURCE_MINIMUM_HBLANK_SUPPORTED, (uint8_t *)(&hblank_size),
+                                       sizeof(hblank_size));
+
+                               if (result_write_min_hblank == DC_ERROR_UNEXPECTED)
+                                       link->preferred_link_setting.dpcd_source_device_specific_field_support = false;
+                       } else {
+                               DC_LOG_DC("Sink device does not support 00340h DPCD write. Skipping on purpose.\n");
+                       }
                }
+
                DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
                                                        WPP_BIT_FLAG_DC_DETECTION_DP_CAPS,
                                                        "result=%u link_index=%u enum dce_version=%d DPCD=0x%04X min_hblank=%u branch_dev_id=0x%x branch_dev_name='%c%c%c%c%c%c'",
index fe234760a0f596c9207e6b26c71ea592ddaa09b6..72970e49800a6ac415475c87f2ef45ffc68a7274 100644 (file)
@@ -1,3 +1,28 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
 #include <inc/core_status.h>
 #include <dc_link.h>
 #include <inc/link_hwss.h>
index 31761f3595a6a609f7c984df69b494b9850fadf3..28ef9760fa34c56184a2f5b55ff3120acf52269a 100644 (file)
@@ -62,3 +62,27 @@ void dc_stat_get_dmub_notification(const struct dc *dc, struct dmub_notification
        status = dmub_srv_stat_get_notification(dmub, notify);
        ASSERT(status == DMUB_STATUS_OK);
 }
+
+/**
+ *****************************************************************************
+ *  Function: dc_stat_get_dmub_dataout
+ *
+ *  @brief
+ *             Calls dmub layer to retrieve dmub gpint dataout
+ *
+ *  @param
+ *             [in] dc: dc structure
+ *             [in] dataout: dmub gpint dataout
+ *
+ *  @return
+ *     None
+ *****************************************************************************
+ */
+void dc_stat_get_dmub_dataout(const struct dc *dc, uint32_t *dataout)
+{
+       struct dmub_srv *dmub = dc->ctx->dmub_srv->dmub;
+       enum dmub_status status;
+
+       status = dmub_srv_get_gpint_dataout(dmub, dataout);
+       ASSERT(status == DMUB_STATUS_OK);
+}
index 45931ee14a6eba7d944248a1ec652908507811b1..327fd1909c5130ecd8d8d2eed58259fa89e322f6 100644 (file)
@@ -221,6 +221,9 @@ struct dc_stream_status *dc_stream_get_status_from_state(
 {
        uint8_t i;
 
+       if (state == NULL)
+               return NULL;
+
        for (i = 0; i < state->stream_count; i++) {
                if (stream == state->streams[i])
                        return &state->stream_status[i];
index 8dcea8ff5c5ad766dc35773910910d7ee41adbe9..a948f4f48935583b5b5cf4d034fa647947259cc3 100644 (file)
@@ -45,7 +45,7 @@
 /* forward declaration */
 struct aux_payload;
 
-#define DC_VER "3.2.141"
+#define DC_VER "3.2.146"
 
 #define MAX_SURFACES 3
 #define MAX_PLANES 6
@@ -458,7 +458,65 @@ union mem_low_power_enable_options {
        uint32_t u32All;
 };
 
+struct dc_debug_data {
+       uint32_t ltFailCount;
+       uint32_t i2cErrorCount;
+       uint32_t auxErrorCount;
+};
+
+struct dc_phy_addr_space_config {
+       struct {
+               uint64_t start_addr;
+               uint64_t end_addr;
+               uint64_t fb_top;
+               uint64_t fb_offset;
+               uint64_t fb_base;
+               uint64_t agp_top;
+               uint64_t agp_bot;
+               uint64_t agp_base;
+       } system_aperture;
+
+       struct {
+               uint64_t page_table_start_addr;
+               uint64_t page_table_end_addr;
+               uint64_t page_table_base_addr;
+               bool base_addr_is_mc_addr;
+       } gart_config;
+
+       bool valid;
+       bool is_hvm_enabled;
+       uint64_t page_table_default_page_addr;
+};
+
+struct dc_virtual_addr_space_config {
+       uint64_t        page_table_base_addr;
+       uint64_t        page_table_start_addr;
+       uint64_t        page_table_end_addr;
+       uint32_t        page_table_block_size_in_bytes;
+       uint8_t         page_table_depth; // 1 = 1 level, 2 = 2 level, etc.  0 = invalid
+};
+
+struct dc_bounding_box_overrides {
+       int sr_exit_time_ns;
+       int sr_enter_plus_exit_time_ns;
+       int urgent_latency_ns;
+       int percent_of_ideal_drambw;
+       int dram_clock_change_latency_ns;
+       int dummy_clock_change_latency_ns;
+       /* This forces a hard min on the DCFCLK we use
+        * for DML.  Unlike the debug option for forcing
+        * DCFCLK, this override affects watermark calculations
+        */
+       int min_dcfclk_mhz;
+};
+
+struct dc_state;
+struct resource_pool;
+struct dce_hwseq;
+
 struct dc_debug_options {
+       bool native422_support;
+       bool disable_dsc;
        enum visual_confirm visual_confirm;
        bool sanity_checks;
        bool max_disp_clk;
@@ -484,7 +542,6 @@ struct dc_debug_options {
        bool disable_dsc_power_gate;
        int dsc_min_slice_height_override;
        int dsc_bpp_increment_div;
-       bool native422_support;
        bool disable_pplib_wm_range;
        enum wm_report_mode pplib_wm_report_mode;
        unsigned int min_disp_clk_khz;
@@ -554,7 +611,6 @@ struct dc_debug_options {
        bool validate_dml_output;
        bool enable_dmcub_surface_flip;
        bool usbc_combo_phy_reset_wa;
-       bool disable_dsc;
        bool enable_dram_clock_change_one_display_vactive;
        union mem_low_power_enable_options enable_mem_low_power;
        bool force_vblank_alignment;
@@ -572,69 +628,13 @@ struct dc_debug_options {
 #endif
 };
 
-struct dc_debug_data {
-       uint32_t ltFailCount;
-       uint32_t i2cErrorCount;
-       uint32_t auxErrorCount;
-};
-
-struct dc_phy_addr_space_config {
-       struct {
-               uint64_t start_addr;
-               uint64_t end_addr;
-               uint64_t fb_top;
-               uint64_t fb_offset;
-               uint64_t fb_base;
-               uint64_t agp_top;
-               uint64_t agp_bot;
-               uint64_t agp_base;
-       } system_aperture;
-
-       struct {
-               uint64_t page_table_start_addr;
-               uint64_t page_table_end_addr;
-               uint64_t page_table_base_addr;
-#if defined(CONFIG_DRM_AMD_DC_DCN)
-               bool base_addr_is_mc_addr;
-#endif
-       } gart_config;
-
-       bool valid;
-       bool is_hvm_enabled;
-       uint64_t page_table_default_page_addr;
-};
-
-struct dc_virtual_addr_space_config {
-       uint64_t        page_table_base_addr;
-       uint64_t        page_table_start_addr;
-       uint64_t        page_table_end_addr;
-       uint32_t        page_table_block_size_in_bytes;
-       uint8_t         page_table_depth; // 1 = 1 level, 2 = 2 level, etc.  0 = invalid
-};
-
-struct dc_bounding_box_overrides {
-       int sr_exit_time_ns;
-       int sr_enter_plus_exit_time_ns;
-       int urgent_latency_ns;
-       int percent_of_ideal_drambw;
-       int dram_clock_change_latency_ns;
-       int dummy_clock_change_latency_ns;
-       /* This forces a hard min on the DCFCLK we use
-        * for DML.  Unlike the debug option for forcing
-        * DCFCLK, this override affects watermark calculations
-        */
-       int min_dcfclk_mhz;
-};
-
-struct resource_pool;
-struct dce_hwseq;
 struct gpu_info_soc_bounding_box_v1_0;
 struct dc {
+       struct dc_debug_options debug;
        struct dc_versions versions;
        struct dc_caps caps;
        struct dc_cap_funcs cap_funcs;
        struct dc_config config;
-       struct dc_debug_options debug;
        struct dc_bounding_box_overrides bb_overrides;
        struct dc_bug_wa work_arounds;
        struct dc_context *ctx;
index 1948cd9427d7e29a799f403d49c34bf299db4c70..4f54bde1bb1c7851e373b1d3d2a6af9b80880ac7 100644 (file)
@@ -109,6 +109,7 @@ struct dc_link_settings {
        enum dc_link_spread link_spread;
        bool use_link_rate_set;
        uint8_t link_rate_set;
+       bool dpcd_source_device_specific_field_support;
 };
 
 struct dc_lane_settings {
index 2a000ba54ddb8603212b874674056c10bc332f62..aacbfd786c6cd78b96da796ada21b96faf892788 100644 (file)
@@ -38,5 +38,6 @@
 #include "dmub/dmub_srv.h"
 
 void dc_stat_get_dmub_notification(const struct dc *dc, struct dmub_notification *notify);
+void dc_stat_get_dmub_dataout(const struct dc *dc, uint32_t *dataout);
 
 #endif /* _DC_STAT_H_ */
index 8016e22114cedeff4ecfe798e927d40982b67a94..c1532930169b73c88f1fba8a6674ec337c9e06aa 100644 (file)
@@ -75,18 +75,6 @@ enum dce_environment {
 #define IS_DIAG_DC(dce_environment) \
        (IS_FPGA_MAXIMUS_DC(dce_environment) || (dce_environment == DCE_ENV_DIAG))
 
-struct hw_asic_id {
-       uint32_t chip_id;
-       uint32_t chip_family;
-       uint32_t pci_revision_id;
-       uint32_t hw_internal_rev;
-       uint32_t vram_type;
-       uint32_t vram_width;
-       uint32_t feature_flags;
-       uint32_t fake_paths_num;
-       void *atombios_base_address;
-};
-
 struct dc_perf_trace {
        unsigned long read_count;
        unsigned long write_count;
@@ -94,36 +82,7 @@ struct dc_perf_trace {
        unsigned long last_entry_write;
 };
 
-struct dc_context {
-       struct dc *dc;
-
-       void *driver_context; /* e.g. amdgpu_device */
-       struct dc_perf_trace *perf_trace;
-       void *cgs_device;
-
-       enum dce_environment dce_environment;
-       struct hw_asic_id asic_id;
-
-       /* todo: below should probably move to dc.  to facilitate removal
-        * of AS we will store these here
-        */
-       enum dce_version dce_version;
-       struct dc_bios *dc_bios;
-       bool created_bios;
-       struct gpio_service *gpio_service;
-       uint32_t dc_sink_id_count;
-       uint32_t dc_stream_id_count;
-       uint32_t dc_edp_id_count;
-       uint64_t fbc_gpu_addr;
-       struct dc_dmub_srv *dmub_srv;
-
-#ifdef CONFIG_DRM_AMD_DC_HDCP
-       struct cp_psp cp_psp;
-#endif
-};
-
-
-#define DC_MAX_EDID_BUFFER_SIZE 1280
+#define DC_MAX_EDID_BUFFER_SIZE 2048
 #define DC_EDID_BLOCK_SIZE 128
 #define MAX_SURFACE_NUM 4
 #define NUM_PIXEL_FORMATS 10
@@ -836,6 +795,46 @@ struct dc_clock_config {
        uint32_t current_clock_khz;/*current clock in use*/
 };
 
+struct hw_asic_id {
+       uint32_t chip_id;
+       uint32_t chip_family;
+       uint32_t pci_revision_id;
+       uint32_t hw_internal_rev;
+       uint32_t vram_type;
+       uint32_t vram_width;
+       uint32_t feature_flags;
+       uint32_t fake_paths_num;
+       void *atombios_base_address;
+};
+
+struct dc_context {
+       struct dc *dc;
+
+       void *driver_context; /* e.g. amdgpu_device */
+       struct dc_perf_trace *perf_trace;
+       void *cgs_device;
+
+       enum dce_environment dce_environment;
+       struct hw_asic_id asic_id;
+
+       /* todo: below should probably move to dc.  to facilitate removal
+        * of AS we will store these here
+        */
+       enum dce_version dce_version;
+       struct dc_bios *dc_bios;
+       bool created_bios;
+       struct gpio_service *gpio_service;
+       uint32_t dc_sink_id_count;
+       uint32_t dc_stream_id_count;
+       uint32_t dc_edp_id_count;
+       uint64_t fbc_gpu_addr;
+       struct dc_dmub_srv *dmub_srv;
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+       struct cp_psp cp_psp;
+#endif
+
+};
+
 /* DSC DPCD capabilities */
 union dsc_slice_caps1 {
        struct {
index 2fb88e54a4bf459d7dbed5e8a519c736b1779b1a..058a9356a39a72563f7a3e393cc500d4d11daa43 100644 (file)
@@ -71,6 +71,8 @@ enum {
 #define DEFAULT_AUX_ENGINE_MULT   0
 #define DEFAULT_AUX_ENGINE_LENGTH 69
 
+#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */
+
 static void release_engine(
        struct dce_aux *engine)
 {
@@ -743,5 +745,11 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
 fail:
        if (!payload_reply)
                payload->reply = NULL;
+
+       DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
+                               WPP_BIT_FLAG_DC_ERROR,
+                               "AUX transaction failed. Result: %d",
+                               operation_result);
+
        return false;
 }
index 10d42ae0cffefd42b09d8955ccbecbd031380f79..1ca8b1d94bc2738ef87fc3446a2d4b2d5694a5f2 100644 (file)
@@ -29,6 +29,8 @@
 #include "dmub/dmub_srv.h"
 #include "core_types.h"
 
+#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */
+
 #define MAX_PIPES 6
 
 /*
@@ -96,10 +98,19 @@ static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state,
                        // Return invalid state when GPINT times out
                        *state = PSR_STATE_INVALID;
 
-               // Assert if max retry hit
-               if (retry_count >= 1000)
-                       ASSERT(0);
        } while (++retry_count <= 1000 && *state == PSR_STATE_INVALID);
+
+       // Assert if max retry hit
+       if (retry_count >= 1000 && *state == PSR_STATE_INVALID) {
+               ASSERT(0);
+               DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
+                               WPP_BIT_FLAG_Firmware_PsrState,
+                               "Unable to get PSR state from FW.");
+       } else
+               DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE,
+                               WPP_BIT_FLAG_Firmware_PsrState,
+                               "Got PSR state from FW. PSR state: %d, Retry count: %d",
+                               *state, retry_count);
 }
 
 /*
@@ -207,7 +218,7 @@ static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level, uint8_
        cmd.psr_set_level.header.sub_type = DMUB_CMD__PSR_SET_LEVEL;
        cmd.psr_set_level.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_level_data);
        cmd.psr_set_level.psr_set_level_data.psr_level = psr_level;
-       cmd.psr_set_level.psr_set_level_data.cmd_version = PSR_VERSION_1;
+       cmd.psr_set_level.psr_set_level_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
        cmd.psr_set_level.psr_set_level_data.panel_inst = panel_inst;
        dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
        dc_dmub_srv_cmd_execute(dc->dmub_srv);
@@ -293,7 +304,7 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
        copy_settings_data->debug.bitfields.use_hw_lock_mgr             = 1;
        copy_settings_data->fec_enable_status = (link->fec_state == dc_link_fec_enabled);
        copy_settings_data->fec_enable_delay_in100us = link->dc->debug.fec_enable_delay_in100us;
-       copy_settings_data->cmd_version =  PSR_VERSION_1;
+       copy_settings_data->cmd_version =  DMUB_CMD_PSR_CONTROL_VERSION_1;
        copy_settings_data->panel_inst = panel_inst;
 
        dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
index 8d7e92d5d3e4b1164dc807889d5cfa937fa5d69d..39485bdeb90ec332fe1321edaf57f2ba8bc7c12a 100644 (file)
@@ -121,6 +121,10 @@ struct dcn_hubbub_registers {
        uint32_t DCN_VM_AGP_BASE;
        uint32_t DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_MSB;
        uint32_t DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB;
+       uint32_t DCN_VM_FAULT_ADDR_MSB;
+       uint32_t DCN_VM_FAULT_ADDR_LSB;
+       uint32_t DCN_VM_FAULT_CNTL;
+       uint32_t DCN_VM_FAULT_STATUS;
        uint32_t DCHUBBUB_ARB_FRAC_URG_BW_NOM_A;
        uint32_t DCHUBBUB_ARB_FRAC_URG_BW_NOM_B;
        uint32_t DCHUBBUB_ARB_FRAC_URG_BW_NOM_C;
@@ -233,7 +237,19 @@ struct dcn_hubbub_registers {
                type DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C;\
                type DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D;\
                type DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_MSB;\
-               type DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB
+               type DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB;\
+               type DCN_VM_FAULT_ADDR_MSB;\
+               type DCN_VM_FAULT_ADDR_LSB;\
+               type DCN_VM_ERROR_STATUS_CLEAR;\
+               type DCN_VM_ERROR_STATUS_MODE;\
+               type DCN_VM_ERROR_INTERRUPT_ENABLE;\
+               type DCN_VM_RANGE_FAULT_DISABLE;\
+               type DCN_VM_PRQ_FAULT_DISABLE;\
+               type DCN_VM_ERROR_STATUS;\
+               type DCN_VM_ERROR_VMID;\
+               type DCN_VM_ERROR_TABLE_LEVEL;\
+               type DCN_VM_ERROR_PIPE;\
+               type DCN_VM_ERROR_INTERRUPT_STATUS
 
 #define HUBBUB_STUTTER_REG_FIELD_LIST(type) \
                type DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A;\
@@ -303,6 +319,7 @@ struct dcn_hubbub_registers {
                type DET3_SIZE_CURRENT;\
                type COMPBUF_SIZE;\
                type COMPBUF_SIZE_CURRENT;\
+               type CONFIG_ERROR;\
                type COMPBUF_RESERVED_SPACE_64B;\
                type COMPBUF_RESERVED_SPACE_ZS;\
                type DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A;\
index 04303fe9c65930ead41850fd84b0c8be3be0d587..ea185c8773232c40b9dd345fba3a6450fc3358d9 100644 (file)
@@ -871,6 +871,8 @@ void hubp1_read_state_common(struct hubp *hubp)
        struct _vcs_dpi_display_dlg_regs_st *dlg_attr = &s->dlg_attr;
        struct _vcs_dpi_display_ttu_regs_st *ttu_attr = &s->ttu_attr;
        struct _vcs_dpi_display_rq_regs_st *rq_regs = &s->rq_regs;
+       uint32_t aperture_low_msb, aperture_low_lsb;
+       uint32_t aperture_high_msb, aperture_high_lsb;
 
        /* Requester */
        REG_GET(HUBPRET_CONTROL,
@@ -881,6 +883,22 @@ void hubp1_read_state_common(struct hubp *hubp)
                        MRQ_EXPANSION_MODE, &rq_regs->mrq_expansion_mode,
                        CRQ_EXPANSION_MODE, &rq_regs->crq_expansion_mode);
 
+       REG_GET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB,
+                       MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, &aperture_low_msb);
+
+       REG_GET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB,
+                       MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, &aperture_low_lsb);
+
+       REG_GET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB,
+                       MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, &aperture_high_msb);
+
+       REG_GET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB,
+                       MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, &aperture_high_lsb);
+
+       // On DCN1, aperture is broken down into MSB and LSB; only keep bits [47:18] to match later DCN format
+       rq_regs->aperture_low_addr = (aperture_low_msb << 26) | (aperture_low_lsb >> 6);
+       rq_regs->aperture_high_addr = (aperture_high_msb << 26) | (aperture_high_lsb >> 6);
+
        /* DLG - Per hubp */
        REG_GET_2(BLANK_OFFSET_0,
                REFCYC_H_BLANK_END, &dlg_attr->refcyc_h_blank_end,
@@ -1037,6 +1055,17 @@ void hubp1_read_state_common(struct hubp *hubp)
                        QoS_LEVEL_LOW_WM, &s->qos_level_low_wm,
                        QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm);
 
+       REG_GET(DCSURF_PRIMARY_SURFACE_ADDRESS,
+                       PRIMARY_SURFACE_ADDRESS, &s->primary_surface_addr_lo);
+
+       REG_GET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH,
+                       PRIMARY_SURFACE_ADDRESS, &s->primary_surface_addr_hi);
+
+       REG_GET(DCSURF_PRIMARY_META_SURFACE_ADDRESS,
+                       PRIMARY_META_SURFACE_ADDRESS, &s->primary_meta_addr_lo);
+
+       REG_GET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH,
+                       PRIMARY_META_SURFACE_ADDRESS, &s->primary_meta_addr_hi);
 }
 
 void hubp1_read_state(struct hubp *hubp)
index e2f2f6995935f062f09443f73d63dca626badc30..9cb8c383d673c7802c0998dbda96ec402fed0b77 100644 (file)
@@ -682,6 +682,10 @@ struct dcn_hubp_state {
        uint32_t min_ttu_vblank;
        uint32_t qos_level_low_wm;
        uint32_t qos_level_high_wm;
+       uint32_t primary_surface_addr_lo;
+       uint32_t primary_surface_addr_hi;
+       uint32_t primary_meta_addr_lo;
+       uint32_t primary_meta_addr_hi;
 };
 
 struct dcn10_hubp {
index c545eddabdcca83f1f9724e99c7459cb5da68304..35af0401f25679e34b85ecbde3c8eef7af7da8a1 100644 (file)
@@ -1502,25 +1502,22 @@ void dcn10_init_hw(struct dc *dc)
 void dcn10_power_down_on_boot(struct dc *dc)
 {
        struct dc_link *edp_links[MAX_NUM_EDP];
-       struct dc_link *edp_link;
+       struct dc_link *edp_link = NULL;
        int edp_num;
        int i = 0;
 
        get_edp_links(dc, edp_links, &edp_num);
-
-       if (edp_num) {
-               for (i = 0; i < edp_num; i++) {
-                       edp_link = edp_links[i];
-                       if (edp_link->link_enc->funcs->is_dig_enabled &&
-                                       edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
-                                       dc->hwseq->funcs.edp_backlight_control &&
-                                       dc->hwss.power_down &&
-                                       dc->hwss.edp_power_control) {
-                               dc->hwseq->funcs.edp_backlight_control(edp_link, false);
-                               dc->hwss.power_down(dc);
-                               dc->hwss.edp_power_control(edp_link, false);
-                       }
-               }
+       if (edp_num)
+               edp_link = edp_links[0];
+
+       if (edp_link && edp_link->link_enc->funcs->is_dig_enabled &&
+                       edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
+                       dc->hwseq->funcs.edp_backlight_control &&
+                       dc->hwss.power_down &&
+                       dc->hwss.edp_power_control) {
+               dc->hwseq->funcs.edp_backlight_control(edp_link, false);
+               dc->hwss.power_down(dc);
+               dc->hwss.edp_power_control(edp_link, false);
        } else {
                for (i = 0; i < dc->link_count; i++) {
                        struct dc_link *link = dc->links[i];
@@ -3180,8 +3177,12 @@ void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data)
 static bool dcn10_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx)
 {
        struct pipe_ctx *test_pipe;
-       const struct rect *r1 = &pipe_ctx->plane_res.scl_data.recout, *r2;
+       const struct scaler_data *scl_data = &pipe_ctx->plane_res.scl_data;
+       const struct rect *r1 = &scl_data->recout, *r2;
        int r1_r = r1->x + r1->width, r1_b = r1->y + r1->height, r2_r, r2_b;
+       int cur_layer = pipe_ctx->plane_state->layer_index;
+       bool upper_pipe_exists = false;
+       struct fixed31_32 one = dc_fixpt_from_int(1);
 
        /**
         * Disable the cursor if there's another pipe above this with a
@@ -3199,8 +3200,17 @@ static bool dcn10_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx)
 
                if (r1->x >= r2->x && r1->y >= r2->y && r1_r <= r2_r && r1_b <= r2_b)
                        return true;
+
+               if (test_pipe->plane_state->layer_index < cur_layer)
+                       upper_pipe_exists = true;
        }
 
+       // if plane scaled, assume an upper plane can handle cursor if it exists.
+       if (upper_pipe_exists &&
+                       (scl_data->ratios.horz.value != one.value ||
+                       scl_data->ratios.vert.value != one.value))
+               return true;
+
        return false;
 }
 
index 3696faf12d866dfdbcb755e1ff29504c4687fc3c..37848f4577b1807f604925d96eeac873200c7266 100644 (file)
@@ -1388,6 +1388,12 @@ void optc1_read_otg_state(struct optc *optc1,
 
        REG_GET(OPTC_INPUT_GLOBAL_CONTROL,
                        OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status);
+
+       REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL,
+                       OTG_VERTICAL_INTERRUPT2_INT_ENABLE, &s->vertical_interrupt2_en);
+
+       REG_GET(OTG_VERTICAL_INTERRUPT2_POSITION,
+                       OTG_VERTICAL_INTERRUPT2_LINE_START, &s->vertical_interrupt2_line);
 }
 
 bool optc1_get_otg_active_size(struct timing_generator *optc,
index 29d6fbe0093a1eb98b4fafe652e60b584cd855b1..c50c29984d51d0be5aa1a86d539408c87dd6d9e8 100644 (file)
@@ -578,6 +578,8 @@ struct dcn_otg_state {
        uint32_t underflow_occurred_status;
        uint32_t otg_enabled;
        uint32_t blank_enabled;
+       uint32_t vertical_interrupt2_en;
+       uint32_t vertical_interrupt2_line;
 };
 
 void optc1_read_otg_state(struct optc *optc1,
index 91a9305d42e89766f28083067890bc604f2cb37a..aacb1fb5c73eb52a1b4f50acefdc8df65dd71b40 100644 (file)
@@ -605,6 +605,26 @@ static bool hubbub2_program_watermarks(
        return wm_pending;
 }
 
+void hubbub2_read_state(struct hubbub *hubbub, struct dcn_hubbub_state *hubbub_state)
+{
+       struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
+
+       if (REG(DCN_VM_FAULT_ADDR_MSB))
+               hubbub_state->vm_fault_addr_msb = REG_READ(DCN_VM_FAULT_ADDR_MSB);
+
+       if (REG(DCN_VM_FAULT_ADDR_LSB))
+               hubbub_state->vm_fault_addr_msb = REG_READ(DCN_VM_FAULT_ADDR_LSB);
+
+       if (REG(DCN_VM_FAULT_CNTL))
+               REG_GET(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_MODE, &hubbub_state->vm_error_mode);
+
+       if (REG(DCN_VM_FAULT_STATUS)) {
+                REG_GET(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_STATUS, &hubbub_state->vm_error_status);
+                REG_GET(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, &hubbub_state->vm_error_vmid);
+                REG_GET(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, &hubbub_state->vm_error_pipe);
+       }
+}
+
 static const struct hubbub_funcs hubbub2_funcs = {
        .update_dchub = hubbub2_update_dchub,
        .init_dchub_sys_ctx = hubbub2_init_dchub_sys_ctx,
@@ -617,6 +637,7 @@ static const struct hubbub_funcs hubbub2_funcs = {
        .program_watermarks = hubbub2_program_watermarks,
        .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
        .allow_self_refresh_control = hubbub1_allow_self_refresh_control,
+       .hubbub_read_state = hubbub2_read_state,
 };
 
 void hubbub2_construct(struct dcn20_hubbub *hubbub,
index 10af257d90efb909a8a43c664b74f334af6d0a95..2f6146bf1d328f162392d74e46357fd7276036ee 100644 (file)
 #include "dcn10/dcn10_hubbub.h"
 #include "dcn20_vmid.h"
 
-#define HUBBUB_REG_LIST_DCN20_COMMON()\
-       HUBBUB_REG_LIST_DCN_COMMON(), \
-       SR(DCHUBBUB_CRC_CTRL), \
-       SR(DCN_VM_FB_LOCATION_BASE),\
-       SR(DCN_VM_FB_LOCATION_TOP),\
-       SR(DCN_VM_FB_OFFSET),\
-       SR(DCN_VM_AGP_BOT),\
-       SR(DCN_VM_AGP_TOP),\
-       SR(DCN_VM_AGP_BASE)
-
 #define TO_DCN20_HUBBUB(hubbub)\
        container_of(hubbub, struct dcn20_hubbub, base)
 
        SR(DCN_VM_FB_OFFSET),\
        SR(DCN_VM_AGP_BOT),\
        SR(DCN_VM_AGP_TOP),\
-       SR(DCN_VM_AGP_BASE)
+       SR(DCN_VM_AGP_BASE),\
+       SR(DCN_VM_FAULT_ADDR_MSB), \
+       SR(DCN_VM_FAULT_ADDR_LSB), \
+       SR(DCN_VM_FAULT_CNTL), \
+       SR(DCN_VM_FAULT_STATUS)
 
 #define HUBBUB_REG_LIST_DCN20(id)\
        HUBBUB_REG_LIST_DCN20_COMMON(), \
        HUBBUB_SF(DCN_VM_AGP_TOP, AGP_TOP, mask_sh), \
        HUBBUB_SF(DCN_VM_AGP_BASE, AGP_BASE, mask_sh), \
        HUBBUB_SF(DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_MSB, DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_MSB, mask_sh), \
-       HUBBUB_SF(DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB, DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB, mask_sh)
+       HUBBUB_SF(DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB, DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_ADDR_MSB, DCN_VM_FAULT_ADDR_MSB, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_ADDR_LSB, DCN_VM_FAULT_ADDR_LSB, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_CLEAR, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_MODE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_INTERRUPT_ENABLE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_RANGE_FAULT_DISABLE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_PRQ_FAULT_DISABLE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_STATUS, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_TABLE_LEVEL, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh)
 
 struct dcn20_hubbub {
        struct hubbub base;
@@ -131,4 +137,7 @@ void hubbub2_get_dchub_ref_freq(struct hubbub *hubbub,
 void hubbub2_wm_read_state(struct hubbub *hubbub,
                struct dcn_hubbub_wm *wm);
 
+void hubbub2_read_state(struct hubbub *hubbub,
+               struct dcn_hubbub_state *hubbub_state);
+
 #endif
index 7e54058715aaba91c8d0040904d9343d0b9fb41b..5adf42a7cc2761e91391b3f9484b000cb6a1a7f0 100644 (file)
@@ -1080,6 +1080,12 @@ void hubp2_read_state_common(struct hubp *hubp)
                        MRQ_EXPANSION_MODE, &rq_regs->mrq_expansion_mode,
                        CRQ_EXPANSION_MODE, &rq_regs->crq_expansion_mode);
 
+       REG_GET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR,
+                       MC_VM_SYSTEM_APERTURE_HIGH_ADDR, &rq_regs->aperture_high_addr);
+
+       REG_GET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR,
+                       MC_VM_SYSTEM_APERTURE_LOW_ADDR, &rq_regs->aperture_low_addr);
+
        /* DLG - Per hubp */
        REG_GET_2(BLANK_OFFSET_0,
                REFCYC_H_BLANK_END, &dlg_attr->refcyc_h_blank_end,
@@ -1236,6 +1242,17 @@ void hubp2_read_state_common(struct hubp *hubp)
                        QoS_LEVEL_LOW_WM, &s->qos_level_low_wm,
                        QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm);
 
+       REG_GET(DCSURF_PRIMARY_SURFACE_ADDRESS,
+                       PRIMARY_SURFACE_ADDRESS, &s->primary_surface_addr_lo);
+
+       REG_GET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH,
+                       PRIMARY_SURFACE_ADDRESS, &s->primary_surface_addr_hi);
+
+       REG_GET(DCSURF_PRIMARY_META_SURFACE_ADDRESS,
+                       PRIMARY_META_SURFACE_ADDRESS, &s->primary_meta_addr_lo);
+
+       REG_GET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH,
+                       PRIMARY_META_SURFACE_ADDRESS, &s->primary_meta_addr_hi);
 }
 
 void hubp2_read_state(struct hubp *hubp)
index b173fa3653b555adf0fb72c9ccfef39ad7423b30..0b1cd1dbed8b5575253c6123a36d860eea00db3c 100644 (file)
@@ -2462,7 +2462,7 @@ void dcn20_set_mcif_arb_params(
                                wb_arb_params->cli_watermark[k] = get_wm_writeback_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
                                wb_arb_params->pstate_watermark[k] = get_wm_writeback_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
                        }
-                       wb_arb_params->time_per_pixel = 16.0 / context->res_ctx.pipe_ctx[i].stream->phy_pix_clk; /* 4 bit fraction, ms */
+                       wb_arb_params->time_per_pixel = 16.0 * 1000 / (context->res_ctx.pipe_ctx[i].stream->phy_pix_clk / 1000); /* 4 bit fraction, ms */
                        wb_arb_params->slice_lines = 32;
                        wb_arb_params->arbitration_slice = 2;
                        wb_arb_params->max_scaled_time = dcn20_calc_max_scaled_time(wb_arb_params->time_per_pixel,
@@ -2531,16 +2531,16 @@ struct pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc,
                 * pick that pipe as secondary
                 * Same logic applies for ODM pipes
                 */
-               if (dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe) {
-                       preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe->pipe_idx;
+               if (dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe) {
+                       preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe->pipe_idx;
                        if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
                                secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
                                secondary_pipe->pipe_idx = preferred_pipe_idx;
                        }
                }
                if (secondary_pipe == NULL &&
-                               dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe) {
-                       preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe->pipe_idx;
+                               dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe) {
+                       preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe->pipe_idx;
                        if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
                                secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
                                secondary_pipe->pipe_idx = preferred_pipe_idx;
index 42fbb5e6d5057ea1f47ea5c653b404063e03fd93..36044cb8ec834a7085fcd57332217a9590f2cee4 100644 (file)
@@ -701,6 +701,7 @@ static const struct hubbub_funcs hubbub21_funcs = {
        .program_watermarks = hubbub21_program_watermarks,
        .allow_self_refresh_control = hubbub1_allow_self_refresh_control,
        .apply_DEDCN21_147_wa = hubbub21_apply_DEDCN21_147_wa,
+       .hubbub_read_state = hubbub2_read_state,
 };
 
 void hubbub21_construct(struct dcn20_hubbub *hubbub,
index ef3ef28509ed5fb248e95d9579611035bc4b99c1..d8eb2bb7282c9705e417847333af562fd4294e8e 100644 (file)
        HUBBUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET, mask_sh), \
        HUBBUB_SF(DCN_VM_AGP_BOT, AGP_BOT, mask_sh), \
        HUBBUB_SF(DCN_VM_AGP_TOP, AGP_TOP, mask_sh), \
-       HUBBUB_SF(DCN_VM_AGP_BASE, AGP_BASE, mask_sh)
+       HUBBUB_SF(DCN_VM_AGP_BASE, AGP_BASE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_ADDR_MSB, DCN_VM_FAULT_ADDR_MSB, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_ADDR_LSB, DCN_VM_FAULT_ADDR_LSB, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_CLEAR, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_MODE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_INTERRUPT_ENABLE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_RANGE_FAULT_DISABLE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_PRQ_FAULT_DISABLE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_STATUS, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_TABLE_LEVEL, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh)
 
 void dcn21_dchvm_init(struct hubbub *hubbub);
 int hubbub21_init_dchub(struct hubbub *hubbub,
index b0c9180b808f6cf577bde2704331cad17b173451..3de1bcf9b3d84163077d16ae914da7e199dbd449 100644 (file)
@@ -833,7 +833,7 @@ static struct hubp_funcs dcn21_hubp_funcs = {
        .dmdata_set_attributes = hubp2_dmdata_set_attributes,
        .dmdata_load = hubp2_dmdata_load,
        .dmdata_status_done = hubp2_dmdata_status_done,
-       .hubp_read_state = hubp1_read_state,
+       .hubp_read_state = hubp2_read_state,
        .hubp_clear_underflow = hubp1_clear_underflow,
        .hubp_set_flip_control_surface_gsl = hubp2_set_flip_control_surface_gsl,
        .hubp_init = hubp21_init,
index f3d98e3ba624310d57dd152f3c51c8ef6eb88eba..f27fc2acac57628cba30acf20126029ee1a967bc 100644 (file)
@@ -109,6 +109,7 @@ struct _vcs_dpi_ip_params_st dcn2_1_ip = {
        .max_page_table_levels = 4,
        .pte_chunk_size_kbytes = 2,
        .meta_chunk_size_kbytes = 2,
+       .min_meta_chunk_size_bytes = 256,
        .writeback_chunk_size_kbytes = 2,
        .line_buffer_size_bits = 789504,
        .is_line_buffer_bpp_fixed = 0,
@@ -883,7 +884,8 @@ static const struct dc_debug_options debug_defaults_drv = {
                .disable_48mhz_pwrdwn = false,
                .usbc_combo_phy_reset_wa = true,
                .dmub_command_table = true,
-               .use_max_lb = true
+               .use_max_lb = true,
+               .optimize_edp_link_rate = true
 };
 
 static const struct dc_debug_options debug_defaults_diags = {
index c0980da6dc491cf863a7d9b2776ca6cdf6e38243..f4414de96acc586e4323c2233dae5aacd9a6671f 100644 (file)
@@ -451,6 +451,7 @@ static const struct hubbub_funcs hubbub30_funcs = {
        .force_wm_propagate_to_pipes = hubbub3_force_wm_propagate_to_pipes,
        .force_pstate_change_control = hubbub3_force_pstate_change_control,
        .init_watermarks = hubbub3_init_watermarks,
+       .hubbub_read_state = hubbub2_read_state,
 };
 
 void hubbub3_construct(struct dcn20_hubbub *hubbub3,
index c0bd0fb09455f4f17a6fb309d710faa40a3fed8f..7b597908b937e05e99ccb935f67b02690ac2bfc5 100644 (file)
        HUBBUB_SF(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, mask_sh), \
        HUBBUB_SF(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, mask_sh), \
        HUBBUB_SF(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, mask_sh), \
-       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, mask_sh)
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_ADDR_MSB, DCN_VM_FAULT_ADDR_MSB, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_ADDR_LSB, DCN_VM_FAULT_ADDR_LSB, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_CLEAR, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_MODE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_INTERRUPT_ENABLE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_RANGE_FAULT_DISABLE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_PRQ_FAULT_DISABLE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_STATUS, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_TABLE_LEVEL, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh)
 
 void hubbub3_construct(struct dcn20_hubbub *hubbub3,
        struct dc_context *ctx,
index c68e3a708a3357dad3a9945e3a5694afebbe8a7d..2e8ab9775fa334087305bc70e2c8d5a09eda6b1f 100644 (file)
@@ -580,22 +580,19 @@ void dcn30_init_hw(struct dc *dc)
         */
        if (dc->config.power_down_display_on_boot) {
                struct dc_link *edp_links[MAX_NUM_EDP];
-               struct dc_link *edp_link;
+               struct dc_link *edp_link = NULL;
 
                get_edp_links(dc, edp_links, &edp_num);
-               if (edp_num) {
-                       for (i = 0; i < edp_num; i++) {
-                               edp_link = edp_links[i];
-                               if (edp_link->link_enc->funcs->is_dig_enabled &&
-                                               edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
-                                               dc->hwss.edp_backlight_control &&
-                                               dc->hwss.power_down &&
-                                               dc->hwss.edp_power_control) {
-                                       dc->hwss.edp_backlight_control(edp_link, false);
-                                       dc->hwss.power_down(dc);
-                                       dc->hwss.edp_power_control(edp_link, false);
-                               }
-                       }
+               if (edp_num)
+                       edp_link = edp_links[0];
+               if (edp_link && edp_link->link_enc->funcs->is_dig_enabled &&
+                               edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
+                               dc->hwss.edp_backlight_control &&
+                               dc->hwss.power_down &&
+                               dc->hwss.edp_power_control) {
+                       dc->hwss.edp_backlight_control(edp_link, false);
+                       dc->hwss.power_down(dc);
+                       dc->hwss.edp_power_control(edp_link, false);
                } else {
                        for (i = 0; i < dc->link_count; i++) {
                                struct dc_link *link = dc->links[i];
index f37e8254df215826f7548a1b5a53f16604483c6e..089be73475918d698120cf2a5756edd2ea3d4199 100644 (file)
@@ -109,11 +109,9 @@ void optc3_lock(struct timing_generator *optc)
        REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
                OTG_MASTER_UPDATE_LOCK, 1);
 
-       /* Should be fast, status does not update on maximus */
-       if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
-               REG_WAIT(OTG_MASTER_UPDATE_LOCK,
-                               UPDATE_LOCK_STATUS, 1,
-                               1, 10);
+       REG_WAIT(OTG_MASTER_UPDATE_LOCK,
+                       UPDATE_LOCK_STATUS, 1,
+                       1, 10);
 }
 
 void optc3_set_out_mux(struct timing_generator *optc, enum otg_out_mux_dest dest)
index a0b96b3c083ffb32a22fba27c58b858d3546fc7b..1e3bd2e9cdcc47cb8a84eb352717c670fb1a590b 100644 (file)
@@ -62,6 +62,7 @@ static const struct hubbub_funcs hubbub301_funcs = {
        .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
        .force_wm_propagate_to_pipes = hubbub3_force_wm_propagate_to_pipes,
        .force_pstate_change_control = hubbub3_force_pstate_change_control,
+       .hubbub_read_state = hubbub2_read_state,
 };
 
 void hubbub301_construct(struct dcn20_hubbub *hubbub3,
index bb9648488900f1db330ca725d5dfff4702da0c04..90c73a1cb98614d42dc9177ed4e5100fa0a2bfc2 100644 (file)
@@ -124,8 +124,8 @@ static void dcn31_program_compbuf_size(struct hubbub *hubbub, unsigned int compb
                ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size
                                + hubbub2->det3_size + compbuf_size_segments <= hubbub2->crb_size_segs);
                REG_UPDATE(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, compbuf_size_segments);
-               REG_WAIT(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT, compbuf_size_segments, 1, 100);
                hubbub2->compbuf_size_segments = compbuf_size_segments;
+               ASSERT(REG_GET(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, &compbuf_size_segments) && !compbuf_size_segments);
        }
 }
 
@@ -876,7 +876,33 @@ static bool hubbub31_get_dcc_compression_cap(struct hubbub *hubbub,
 static int hubbub31_init_dchub_sys_ctx(struct hubbub *hubbub,
                struct dcn_hubbub_phys_addr_config *pa_config)
 {
-       hubbub3_init_dchub_sys_ctx(hubbub, pa_config);
+       struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+       struct dcn_vmid_page_table_config phys_config;
+
+       REG_SET(DCN_VM_FB_LOCATION_BASE, 0,
+                       FB_BASE, pa_config->system_aperture.fb_base >> 24);
+       REG_SET(DCN_VM_FB_LOCATION_TOP, 0,
+                       FB_TOP, pa_config->system_aperture.fb_top >> 24);
+       REG_SET(DCN_VM_FB_OFFSET, 0,
+                       FB_OFFSET, pa_config->system_aperture.fb_offset >> 24);
+       REG_SET(DCN_VM_AGP_BOT, 0,
+                       AGP_BOT, pa_config->system_aperture.agp_bot >> 24);
+       REG_SET(DCN_VM_AGP_TOP, 0,
+                       AGP_TOP, pa_config->system_aperture.agp_top >> 24);
+       REG_SET(DCN_VM_AGP_BASE, 0,
+                       AGP_BASE, pa_config->system_aperture.agp_base >> 24);
+
+       if (pa_config->gart_config.page_table_start_addr != pa_config->gart_config.page_table_end_addr) {
+               phys_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr >> 12;
+               phys_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr >> 12;
+               phys_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;
+               phys_config.depth = 0;
+               phys_config.block_size = 0;
+               // Init VMID 0 based on PA config
+               dcn20_vmid_setup(&hubbub2->vmid[0], &phys_config);
+
+               dcn20_vmid_setup(&hubbub2->vmid[15], &phys_config);
+       }
 
        dcn21_dchvm_init(hubbub);
 
@@ -934,7 +960,8 @@ static const struct hubbub_funcs hubbub31_funcs = {
        .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
        .program_det_size = dcn31_program_det_size,
        .program_compbuf_size = dcn31_program_compbuf_size,
-       .init_crb = dcn31_init_crb
+       .init_crb = dcn31_init_crb,
+       .hubbub_read_state = hubbub2_read_state,
 };
 
 void hubbub31_construct(struct dcn20_hubbub *hubbub31,
index 8ec98cbcbd47b4f02d2ea46fdbba82ea48715dc9..e3a654bf04e8655238ef908526b1f52b2b917d34 100644 (file)
@@ -98,6 +98,7 @@
        HUBBUB_SF(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, mask_sh),\
        HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, mask_sh),\
        HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, mask_sh),\
        HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_64B, mask_sh),\
        HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_ZS, mask_sh),\
        HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, mask_sh), \
        HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, mask_sh), \
        HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, mask_sh), \
        HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, mask_sh), \
-       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, mask_sh)
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_ADDR_MSB, DCN_VM_FAULT_ADDR_MSB, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_ADDR_LSB, DCN_VM_FAULT_ADDR_LSB, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_CLEAR, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_MODE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_INTERRUPT_ENABLE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_RANGE_FAULT_DISABLE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_PRQ_FAULT_DISABLE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_STATUS, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_TABLE_LEVEL, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh)
 
 
 void hubbub31_construct(struct dcn20_hubbub *hubbub3,
index 6ac6faf0c533babff7fc13421f059815affe2d75..83f7904630e6b0aaca4c5e60d484ad5c7717fc4d 100644 (file)
@@ -226,6 +226,7 @@ void dcn31_init_hw(struct dc *dc)
        if (dc->config.power_down_display_on_boot) {
                struct dc_link *edp_links[MAX_NUM_EDP];
                struct dc_link *edp_link;
+               bool power_down = false;
 
                get_edp_links(dc, edp_links, &edp_num);
                if (edp_num) {
@@ -239,9 +240,11 @@ void dcn31_init_hw(struct dc *dc)
                                        dc->hwss.edp_backlight_control(edp_link, false);
                                        dc->hwss.power_down(dc);
                                        dc->hwss.edp_power_control(edp_link, false);
+                                       power_down = true;
                                }
                        }
-               } else {
+               }
+               if (!power_down) {
                        for (i = 0; i < dc->link_count; i++) {
                                struct dc_link *link = dc->links[i];
 
index d25a7d38d21feed634a3a0fab81fe40272fe404a..4136eb8256cb53509c06dcffbc1d67cc784881ff 100644 (file)
@@ -841,6 +841,9 @@ static bool CalculatePrefetchSchedule(
        else
                *DestinationLinesForPrefetch = dst_y_prefetch_equ;
 
+       // Limit to prevent overflow in DST_Y_PREFETCH register
+       *DestinationLinesForPrefetch = dml_min(*DestinationLinesForPrefetch, 63.75);
+
        dml_print("DML: VStartup: %d\n", VStartup);
        dml_print("DML: TCalc: %f\n", TCalc);
        dml_print("DML: TWait: %f\n", TWait);
@@ -2267,7 +2270,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
                                        &locals->UrgentBurstFactorLumaPre[k],
                                        &locals->UrgentBurstFactorChroma[k],
                                        &locals->UrgentBurstFactorChromaPre[k],
-                                       &locals->NotEnoughUrgentLatencyHiding,
+                                       &locals->NotEnoughUrgentLatencyHiding[0][0],
                                        &locals->NotEnoughUrgentLatencyHidingPre);
 
                        if (mode_lib->vba.UseUrgentBurstBandwidth == false) {
@@ -2300,7 +2303,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
                }
                mode_lib->vba.FractionOfUrgentBandwidth = MaxTotalRDBandwidthNoUrgentBurst / mode_lib->vba.ReturnBW;
 
-               if (MaxTotalRDBandwidth <= mode_lib->vba.ReturnBW && locals->NotEnoughUrgentLatencyHiding == 0 && locals->NotEnoughUrgentLatencyHidingPre == 0 && !VRatioPrefetchMoreThan4
+               if (MaxTotalRDBandwidth <= mode_lib->vba.ReturnBW && locals->NotEnoughUrgentLatencyHiding[0][0] == 0 &&
+                               locals->NotEnoughUrgentLatencyHidingPre == 0 && !VRatioPrefetchMoreThan4
                                && !DestinationLineTimesForPrefetchLessThan2)
                        mode_lib->vba.PrefetchModeSupported = true;
                else {
@@ -4821,7 +4825,7 @@ void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                                        &locals->UrgentBurstFactorLumaPre[k],
                                                        &locals->UrgentBurstFactorChroma[k],
                                                        &locals->UrgentBurstFactorChromaPre[k],
-                                                       &locals->NotEnoughUrgentLatencyHiding,
+                                                       &locals->NotEnoughUrgentLatencyHiding[0][0],
                                                        &locals->NotEnoughUrgentLatencyHidingPre);
 
                                        if (mode_lib->vba.UseUrgentBurstBandwidth == false) {
@@ -4848,13 +4852,13 @@ void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                }
                                locals->BandwidthWithoutPrefetchSupported[i][0] = true;
                                if (mode_lib->vba.MaximumReadBandwidthWithoutPrefetch > locals->ReturnBWPerState[i][0]
-                                               || locals->NotEnoughUrgentLatencyHiding == 1) {
+                                               || locals->NotEnoughUrgentLatencyHiding[0][0] == 1) {
                                        locals->BandwidthWithoutPrefetchSupported[i][0] = false;
                                }
 
                                locals->PrefetchSupported[i][j] = true;
                                if (mode_lib->vba.MaximumReadBandwidthWithPrefetch > locals->ReturnBWPerState[i][0]
-                                               || locals->NotEnoughUrgentLatencyHiding == 1
+                                               || locals->NotEnoughUrgentLatencyHiding[0][0] == 1
                                                || locals->NotEnoughUrgentLatencyHidingPre == 1) {
                                        locals->PrefetchSupported[i][j] = false;
                                }
index 9d2016d8fafeeee396e5d44b0319403f322e7ad4..e1a961a62addba7737fd1e29dd3dce4636b0d1ca 100644 (file)
@@ -2596,7 +2596,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
                        }
                }
 
-               v->NotEnoughUrgentLatencyHiding = false;
+               v->NotEnoughUrgentLatencyHiding[0][0] = false;
                v->NotEnoughUrgentLatencyHidingPre = false;
 
                for (k = 0; k < v->NumberOfActivePlanes; ++k) {
@@ -2681,7 +2681,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
                        if (v->VRatioPrefetchY[k] > 4 || v->VRatioPrefetchC[k] > 4)
                                VRatioPrefetchMoreThan4 = true;
                        if (v->NoUrgentLatencyHiding[k] == true)
-                               v->NotEnoughUrgentLatencyHiding = true;
+                               v->NotEnoughUrgentLatencyHiding[0][0] = true;
 
                        if (v->NoUrgentLatencyHidingPre[k] == true)
                                v->NotEnoughUrgentLatencyHidingPre = true;
@@ -2689,7 +2689,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
                v->FractionOfUrgentBandwidth = MaxTotalRDBandwidthNoUrgentBurst / v->ReturnBW;
 
 
-               if (MaxTotalRDBandwidth <= v->ReturnBW && v->NotEnoughUrgentLatencyHiding == 0 && v->NotEnoughUrgentLatencyHidingPre == 0 && !VRatioPrefetchMoreThan4
+               if (MaxTotalRDBandwidth <= v->ReturnBW && v->NotEnoughUrgentLatencyHiding[0][0] == 0
+                               && v->NotEnoughUrgentLatencyHidingPre == 0 && !VRatioPrefetchMoreThan4
                                && !DestinationLineTimesForPrefetchLessThan2)
                        v->PrefetchModeSupported = true;
                else {
@@ -2794,8 +2795,9 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
                }
 
                v->VStartupLines = v->VStartupLines + 1;
-               v->PrefetchAndImmediateFlipSupported = (v->PrefetchModeSupported == true && ((!v->ImmediateFlipSupport && !v->HostVMEnable && v->ImmediateFlipRequirement != dm_immediate_flip_required) || v->ImmediateFlipSupported)) ? true : false;
-
+               v->PrefetchModeSupported = (v->PrefetchModeSupported == true && ((!v->ImmediateFlipSupport &&
+                               !v->HostVMEnable && v->ImmediateFlipRequirement[0] != dm_immediate_flip_required) ||
+                               v->ImmediateFlipSupported)) ? true : false;
        } while (!v->PrefetchModeSupported && v->VStartupLines <= v->MaximumMaxVStartupLines);
        ASSERT(v->PrefetchModeSupported);
 
@@ -4753,7 +4755,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                v->HostVMMinPageSize,
                                v->HostVMMaxNonCachedPageTableLevels,
                                v->DynamicMetadataVMEnabled,
-                               v->ImmediateFlipRequirement,
+                               v->ImmediateFlipRequirement[0],
                                v->ProgressiveToInterlaceUnitInOPP,
                                v->MaxAveragePercentOfIdealSDPPortBWDisplayCanUseInNormalSystemOperation,
                                v->PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData,
@@ -5164,7 +5166,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                        v->NextMaxVStartup = v->NextMaxVStartup - 1;
                                }
                        } while (!((v->PrefetchSupported[i][j] == true && v->DynamicMetadataSupported[i][j] == true && v->VRatioInPrefetchSupported[i][j] == true
-                                       && ((v->HostVMEnable == false && v->ImmediateFlipRequirement != dm_immediate_flip_required)
+                                       && ((v->HostVMEnable == false && v->ImmediateFlipRequirement[0] != dm_immediate_flip_required)
                                                        || v->ImmediateFlipSupportedForState[i][j] == true))
                                        || (v->NextMaxVStartup == v->MaxMaxVStartup[i][j] && NextPrefetchModeState > MaxPrefetchMode)));
 
@@ -5305,7 +5307,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                        && ViewportExceedsSurface == 0 && v->PrefetchSupported[i][j] == 1 && v->DynamicMetadataSupported[i][j] == 1
                                        && v->TotalVerticalActiveBandwidthSupport[i][j] == 1 && v->VRatioInPrefetchSupported[i][j] == 1
                                        && v->PTEBufferSizeNotExceeded[i][j] == 1 && v->NonsupportedDSCInputBPC == 0
-                                       && ((v->HostVMEnable == 0 && v->ImmediateFlipRequirement != dm_immediate_flip_required)
+                                       && ((v->HostVMEnable == 0 && v->ImmediateFlipRequirement[0] != dm_immediate_flip_required)
                                                        || v->ImmediateFlipSupportedForState[i][j] == true)) {
                                v->ModeSupport[i][j] = true;
                        } else {
index a9667068c6901f960c45f80acbdaca322d65f65a..ce55c9caf9a270159e79caa49e5fe416642e934a 100644 (file)
@@ -3036,10 +3036,9 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
                }
 
                v->PrefetchAndImmediateFlipSupported =
-                               (v->PrefetchModeSupported == true
-                                               && ((!v->ImmediateFlipSupport && !v->HostVMEnable
-                                                               && v->ImmediateFlipRequirement != dm_immediate_flip_required) || v->ImmediateFlipSupported)) ?
-                                               true : false;
+                               (v->PrefetchModeSupported == true && ((!v->ImmediateFlipSupport && !v->HostVMEnable
+                               && v->ImmediateFlipRequirement[0] != dm_immediate_flip_required) ||
+                               v->ImmediateFlipSupported)) ? true : false;
 #ifdef __DML_VBA_DEBUG__
                dml_print("DML::%s: PrefetchModeSupported %d\n", __func__, v->PrefetchModeSupported);
                dml_print("DML::%s: ImmediateFlipRequirement %d\n", __func__, v->ImmediateFlipRequirement == dm_immediate_flip_required);
@@ -5103,7 +5102,7 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                v->HostVMMinPageSize,
                                v->HostVMMaxNonCachedPageTableLevels,
                                v->DynamicMetadataVMEnabled,
-                               v->ImmediateFlipRequirement,
+                               v->ImmediateFlipRequirement[0],
                                v->ProgressiveToInterlaceUnitInOPP,
                                v->MaxAveragePercentOfIdealFabricAndSDPPortBWDisplayCanUseInNormalSystemOperation,
                                v->PercentOfIdealFabricAndSDPPortBWReceivedAfterUrgLatency,
@@ -5542,7 +5541,8 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                }
                                v->NextPrefetchMode = v->NextPrefetchMode + 1;
                        } while (!((v->PrefetchSupported[i][j] == true && v->DynamicMetadataSupported[i][j] == true && v->VRatioInPrefetchSupported[i][j] == true
-                                       && ((v->HostVMEnable == false && v->ImmediateFlipRequirement != dm_immediate_flip_required)
+                                       && ((v->HostVMEnable == false &&
+                                                       v->ImmediateFlipRequirement[0] != dm_immediate_flip_required)
                                                        || v->ImmediateFlipSupportedForState[i][j] == true))
                                        || (v->NextMaxVStartup == v->MaxMaxVStartup[i][j] && NextPrefetchModeState > MaxPrefetchMode)));
 
@@ -5702,7 +5702,8 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                        && v->PrefetchSupported[i][j] == true && v->DynamicMetadataSupported[i][j] == true
                                        && v->TotalVerticalActiveBandwidthSupport[i][j] == true && v->VRatioInPrefetchSupported[i][j] == true
                                        && v->PTEBufferSizeNotExceeded[i][j] == true && v->NonsupportedDSCInputBPC == false
-                                       && ((v->HostVMEnable == false && v->ImmediateFlipRequirement != dm_immediate_flip_required)
+                                       && ((v->HostVMEnable == false
+                                       && v->ImmediateFlipRequirement[0] != dm_immediate_flip_required)
                                                        || v->ImmediateFlipSupportedForState[i][j] == true)
                                        && FMTBufferExceeded == false) {
                                v->ModeSupport[i][j] = true;
index 64f9c735f74d8a80c5b02bcf6ad84c0264a52d88..1051ca1a23b8a2aa166f44c43eb4bc89db662eeb 100644 (file)
@@ -109,7 +109,9 @@ enum clock_change_support {
 };
 
 enum output_standard {
-       dm_std_uninitialized = 0, dm_std_cvtr2, dm_std_cvt
+       dm_std_uninitialized = 0,
+       dm_std_cvtr2,
+       dm_std_cvt
 };
 
 enum mpc_combine_affinity {
index 64daa0507393409f4fa4db3ab285f4558608726e..d46a2733024ce5aeb78a606ee16bb4cea277f1f7 100644 (file)
@@ -536,6 +536,8 @@ struct _vcs_dpi_display_rq_regs_st {
        unsigned int mrq_expansion_mode;
        unsigned int crq_expansion_mode;
        unsigned int plane1_base_address;
+       unsigned int aperture_low_addr;   // bits [47:18]
+       unsigned int aperture_high_addr;  // bits [47:18]
 };
 
 struct _vcs_dpi_display_dlg_sys_params_st {
index d3b1b6d4ce2f9df4de6d3309381c30b16f78cdd9..73f5be26abc4dbebbfa74a01d30fda6b5050a8f8 100644 (file)
@@ -396,7 +396,6 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib)
 
        mode_lib->vba.NumberOfActivePlanes = 0;
        mode_lib->vba.ImmediateFlipSupport = false;
-       mode_lib->vba.ImmediateFlipRequirement = dm_immediate_flip_not_required;
        for (j = 0; j < mode_lib->vba.cache_num_pipes; ++j) {
                display_pipe_source_params_st *src = &pipes[j].pipe.src;
                display_pipe_dest_params_st *dst = &pipes[j].pipe.dest;
@@ -409,6 +408,7 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib)
                        continue;
                visited[j] = true;
 
+               mode_lib->vba.ImmediateFlipRequirement[j] = dm_immediate_flip_not_required;
                mode_lib->vba.pipe_plane[j] = mode_lib->vba.NumberOfActivePlanes;
                mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes] = 1;
                mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] =
@@ -667,9 +667,9 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib)
                                mode_lib->vba.ViewportHeightChroma[mode_lib->vba.NumberOfActivePlanes] = src->viewport_height_max / vdiv_c;
                }
 
-               if (pipes[k].pipe.src.immediate_flip) {
+               if (pipes[j].pipe.src.immediate_flip) {
                        mode_lib->vba.ImmediateFlipSupport = true;
-                       mode_lib->vba.ImmediateFlipRequirement = dm_immediate_flip_required;
+                       mode_lib->vba.ImmediateFlipRequirement[j] = dm_immediate_flip_required;
                }
 
                mode_lib->vba.NumberOfActivePlanes++;
@@ -845,9 +845,10 @@ void PixelClockAdjustmentForProgressiveToInterlaceUnit(struct display_mode_lib *
 
        //Progressive To Interlace Unit Effect
        for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
+               mode_lib->vba.PixelClockBackEnd[k] = mode_lib->vba.PixelClock[k];
                if (mode_lib->vba.Interlace[k] == 1
                                && mode_lib->vba.ProgressiveToInterlaceUnitInOPP == true) {
-                       mode_lib->vba.PixelClock[k] = 2 * mode_lib->vba.PixelClockBackEnd[k];
+                       mode_lib->vba.PixelClock[k] = 2 * mode_lib->vba.PixelClock[k];
                }
        }
 }
@@ -890,8 +891,9 @@ void ModeSupportAndSystemConfiguration(struct display_mode_lib *mode_lib)
                mode_lib->vba.DISPCLK = soc->clock_limits[mode_lib->vba.VoltageLevel].dispclk_mhz;
 
        // Total Available Pipes Support Check
-       for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k)
+       for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
                total_pipes += mode_lib->vba.DPPPerPlane[k];
+       }
        ASSERT(total_pipes <= DC__NUM_DPP__MAX);
 }
 
index d18a021d4d32128d23ccd1c98cea457091167afb..90e87961fe3ebb96146e5556686fd8ebc5975134 100644 (file)
@@ -676,7 +676,7 @@ struct vba_vars_st {
        double         AlignedDCCMetaPitchY[DC__NUM_DPP__MAX];
        double         AlignedDCCMetaPitchC[DC__NUM_DPP__MAX];
 
-       unsigned int NotEnoughUrgentLatencyHiding;
+       unsigned int NotEnoughUrgentLatencyHiding[DC__VOLTAGE_STATES][2];
        unsigned int NotEnoughUrgentLatencyHidingPre;
        int PTEBufferSizeInRequestsForLuma;
        int PTEBufferSizeInRequestsForChroma;
@@ -877,7 +877,7 @@ struct vba_vars_st {
 
        int PercentMarginOverMinimumRequiredDCFCLK;
        bool DynamicMetadataSupported[DC__VOLTAGE_STATES][2];
-       enum immediate_flip_requirement ImmediateFlipRequirement;
+       enum immediate_flip_requirement ImmediateFlipRequirement[DC__NUM_DPP__MAX];
        unsigned int DETBufferSizeYThisState[DC__NUM_DPP__MAX];
        unsigned int DETBufferSizeCThisState[DC__NUM_DPP__MAX];
        bool NoUrgentLatencyHiding[DC__NUM_DPP__MAX];
index f403d8e84a8c1e8d6e16e8e3ddef1773d3440881..f5b7da0e64c0701ac640f079b73f59c5f1b81c6e 100644 (file)
@@ -28,6 +28,7 @@
 #include <drm/drm_dp_helper.h>
 #include "dc.h"
 #include "rc_calc.h"
+#include "fixed31_32.h"
 
 /* This module's internal functions */
 
@@ -39,6 +40,47 @@ static bool dsc_policy_enable_dsc_when_not_needed;
 
 static bool dsc_policy_disable_dsc_stream_overhead;
 
+/* Forward Declerations */
+static void get_dsc_bandwidth_range(
+               const uint32_t min_bpp_x16,
+               const uint32_t max_bpp_x16,
+               const uint32_t num_slices_h,
+               const struct dsc_enc_caps *dsc_caps,
+               const struct dc_crtc_timing *timing,
+               struct dc_dsc_bw_range *range);
+
+static uint32_t compute_bpp_x16_from_target_bandwidth(
+               const uint32_t bandwidth_in_kbps,
+               const struct dc_crtc_timing *timing,
+               const uint32_t num_slices_h,
+               const uint32_t bpp_increment_div,
+               const bool is_dp);
+
+static void get_dsc_enc_caps(
+               const struct display_stream_compressor *dsc,
+               struct dsc_enc_caps *dsc_enc_caps,
+               int pixel_clock_100Hz);
+
+static bool intersect_dsc_caps(
+               const struct dsc_dec_dpcd_caps *dsc_sink_caps,
+               const struct dsc_enc_caps *dsc_enc_caps,
+               enum dc_pixel_encoding pixel_encoding,
+               struct dsc_enc_caps *dsc_common_caps);
+
+static bool setup_dsc_config(
+               const struct dsc_dec_dpcd_caps *dsc_sink_caps,
+               const struct dsc_enc_caps *dsc_enc_caps,
+               int target_bandwidth_kbps,
+               const struct dc_crtc_timing *timing,
+               int min_slice_height_override,
+               int max_dsc_target_bpp_limit_override_x16,
+               struct dc_dsc_config *dsc_cfg);
+
+static struct fixed31_32 compute_dsc_max_bandwidth_overhead(
+               const struct dc_crtc_timing *timing,
+               const int num_slices_h,
+               const bool is_dp);
+
 static bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size)
 {
 
@@ -171,10 +213,164 @@ static bool dsc_bpp_increment_div_from_dpcd(uint8_t bpp_increment_dpcd, uint32_t
        return true;
 }
 
+
+
+bool dc_dsc_parse_dsc_dpcd(const struct dc *dc,
+               const uint8_t *dpcd_dsc_basic_data,
+               const uint8_t *dpcd_dsc_branch_decoder_caps,
+               struct dsc_dec_dpcd_caps *dsc_sink_caps)
+{
+       if (!dpcd_dsc_basic_data)
+               return false;
+
+       dsc_sink_caps->is_dsc_supported =
+               (dpcd_dsc_basic_data[DP_DSC_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_DECOMPRESSION_IS_SUPPORTED) != 0;
+       if (!dsc_sink_caps->is_dsc_supported)
+               return false;
+
+       dsc_sink_caps->dsc_version = dpcd_dsc_basic_data[DP_DSC_REV - DP_DSC_SUPPORT];
+
+       {
+               int buff_block_size;
+               int buff_size;
+
+               if (!dsc_buff_block_size_from_dpcd(dpcd_dsc_basic_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT],
+                                                                                  &buff_block_size))
+                       return false;
+
+               buff_size = dpcd_dsc_basic_data[DP_DSC_RC_BUF_SIZE - DP_DSC_SUPPORT] + 1;
+               dsc_sink_caps->rc_buffer_size = buff_size * buff_block_size;
+       }
+
+       dsc_sink_caps->slice_caps1.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_1 - DP_DSC_SUPPORT];
+       if (!dsc_line_buff_depth_from_dpcd(dpcd_dsc_basic_data[DP_DSC_LINE_BUF_BIT_DEPTH - DP_DSC_SUPPORT],
+                                                                          &dsc_sink_caps->lb_bit_depth))
+               return false;
+
+       dsc_sink_caps->is_block_pred_supported =
+               (dpcd_dsc_basic_data[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] &
+                DP_DSC_BLK_PREDICTION_IS_SUPPORTED) != 0;
+
+       dsc_sink_caps->edp_max_bits_per_pixel =
+               dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_LOW - DP_DSC_SUPPORT] |
+               dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] << 8;
+
+       dsc_sink_caps->color_formats.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT];
+       dsc_sink_caps->color_depth.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_DEPTH_CAP - DP_DSC_SUPPORT];
+
+       {
+               int dpcd_throughput = dpcd_dsc_basic_data[DP_DSC_PEAK_THROUGHPUT - DP_DSC_SUPPORT];
+
+               if (!dsc_throughput_from_dpcd(dpcd_throughput & DP_DSC_THROUGHPUT_MODE_0_MASK,
+                                                                         &dsc_sink_caps->throughput_mode_0_mps))
+                       return false;
+
+               dpcd_throughput = (dpcd_throughput & DP_DSC_THROUGHPUT_MODE_1_MASK) >> DP_DSC_THROUGHPUT_MODE_1_SHIFT;
+               if (!dsc_throughput_from_dpcd(dpcd_throughput, &dsc_sink_caps->throughput_mode_1_mps))
+                       return false;
+       }
+
+       dsc_sink_caps->max_slice_width = dpcd_dsc_basic_data[DP_DSC_MAX_SLICE_WIDTH - DP_DSC_SUPPORT] * 320;
+       dsc_sink_caps->slice_caps2.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT];
+
+       if (!dsc_bpp_increment_div_from_dpcd(dpcd_dsc_basic_data[DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT],
+                                                                                &dsc_sink_caps->bpp_increment_div))
+               return false;
+
+       if (dc->debug.dsc_bpp_increment_div) {
+               /* dsc_bpp_increment_div should onl be 1, 2, 4, 8 or 16, but rather than rejecting invalid values,
+                * we'll accept all and get it into range. This also makes the above check against 0 redundant,
+                * but that one stresses out the override will be only used if it's not 0.
+                */
+               if (dc->debug.dsc_bpp_increment_div >= 1)
+                       dsc_sink_caps->bpp_increment_div = 1;
+               if (dc->debug.dsc_bpp_increment_div >= 2)
+                       dsc_sink_caps->bpp_increment_div = 2;
+               if (dc->debug.dsc_bpp_increment_div >= 4)
+                       dsc_sink_caps->bpp_increment_div = 4;
+               if (dc->debug.dsc_bpp_increment_div >= 8)
+                       dsc_sink_caps->bpp_increment_div = 8;
+               if (dc->debug.dsc_bpp_increment_div >= 16)
+                       dsc_sink_caps->bpp_increment_div = 16;
+       }
+
+       /* Extended caps */
+       if (dpcd_dsc_branch_decoder_caps == NULL) { // branch decoder DPCD DSC data can be null for non branch device
+               dsc_sink_caps->branch_overall_throughput_0_mps = 0;
+               dsc_sink_caps->branch_overall_throughput_1_mps = 0;
+               dsc_sink_caps->branch_max_line_width = 0;
+               return true;
+       }
+
+       dsc_sink_caps->branch_overall_throughput_0_mps =
+               dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_0 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];
+       if (dsc_sink_caps->branch_overall_throughput_0_mps == 0)
+               dsc_sink_caps->branch_overall_throughput_0_mps = 0;
+       else if (dsc_sink_caps->branch_overall_throughput_0_mps == 1)
+               dsc_sink_caps->branch_overall_throughput_0_mps = 680;
+       else {
+               dsc_sink_caps->branch_overall_throughput_0_mps *= 50;
+               dsc_sink_caps->branch_overall_throughput_0_mps += 600;
+       }
+
+       dsc_sink_caps->branch_overall_throughput_1_mps =
+               dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_1 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];
+       if (dsc_sink_caps->branch_overall_throughput_1_mps == 0)
+               dsc_sink_caps->branch_overall_throughput_1_mps = 0;
+       else if (dsc_sink_caps->branch_overall_throughput_1_mps == 1)
+               dsc_sink_caps->branch_overall_throughput_1_mps = 680;
+       else {
+               dsc_sink_caps->branch_overall_throughput_1_mps *= 50;
+               dsc_sink_caps->branch_overall_throughput_1_mps += 600;
+       }
+
+       dsc_sink_caps->branch_max_line_width =
+               dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_MAX_LINE_WIDTH - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0] * 320;
+       ASSERT(dsc_sink_caps->branch_max_line_width == 0 || dsc_sink_caps->branch_max_line_width >= 5120);
+
+       dsc_sink_caps->is_dp = true;
+       return true;
+}
+
+
+/* If DSC is possbile, get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range and
+ * timing's pixel clock and uncompressed bandwidth.
+ * If DSC is not possible, leave '*range' untouched.
+ */
+bool dc_dsc_compute_bandwidth_range(
+               const struct display_stream_compressor *dsc,
+               uint32_t dsc_min_slice_height_override,
+               uint32_t min_bpp_x16,
+               uint32_t max_bpp_x16,
+               const struct dsc_dec_dpcd_caps *dsc_sink_caps,
+               const struct dc_crtc_timing *timing,
+               struct dc_dsc_bw_range *range)
+{
+       bool is_dsc_possible = false;
+       struct dsc_enc_caps dsc_enc_caps;
+       struct dsc_enc_caps dsc_common_caps;
+       struct dc_dsc_config config;
+
+       get_dsc_enc_caps(dsc, &dsc_enc_caps, timing->pix_clk_100hz);
+
+       is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, &dsc_enc_caps,
+                       timing->pixel_encoding, &dsc_common_caps);
+
+       if (is_dsc_possible)
+               is_dsc_possible = setup_dsc_config(dsc_sink_caps, &dsc_enc_caps, 0, timing,
+                               dsc_min_slice_height_override, max_bpp_x16, &config);
+
+       if (is_dsc_possible)
+               get_dsc_bandwidth_range(min_bpp_x16, max_bpp_x16,
+                               config.num_slices_h, &dsc_common_caps, timing, range);
+
+       return is_dsc_possible;
+}
+
 static void get_dsc_enc_caps(
-       const struct display_stream_compressor *dsc,
-       struct dsc_enc_caps *dsc_enc_caps,
-       int pixel_clock_100Hz)
+               const struct display_stream_compressor *dsc,
+               struct dsc_enc_caps *dsc_enc_caps,
+               int pixel_clock_100Hz)
 {
        // This is a static HW query, so we can use any DSC
 
@@ -187,14 +383,14 @@ static void get_dsc_enc_caps(
        }
 }
 
-/* Returns 'false' if no intersection was found for at least one capablity.
+/* Returns 'false' if no intersection was found for at least one capability.
  * It also implicitly validates some sink caps against invalid value of zero.
  */
 static bool intersect_dsc_caps(
-       const struct dsc_dec_dpcd_caps *dsc_sink_caps,
-       const struct dsc_enc_caps *dsc_enc_caps,
-       enum dc_pixel_encoding pixel_encoding,
-       struct dsc_enc_caps *dsc_common_caps)
+               const struct dsc_dec_dpcd_caps *dsc_sink_caps,
+               const struct dsc_enc_caps *dsc_enc_caps,
+               enum dc_pixel_encoding pixel_encoding,
+               struct dsc_enc_caps *dsc_common_caps)
 {
        int32_t max_slices;
        int32_t total_sink_throughput;
@@ -205,10 +401,14 @@ static bool intersect_dsc_caps(
        if (!dsc_common_caps->dsc_version)
                return false;
 
-       dsc_common_caps->slice_caps.bits.NUM_SLICES_1 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_1 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_1;
-       dsc_common_caps->slice_caps.bits.NUM_SLICES_2 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_2 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_2;
-       dsc_common_caps->slice_caps.bits.NUM_SLICES_4 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_4 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_4;
-       dsc_common_caps->slice_caps.bits.NUM_SLICES_8 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_8 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_8;
+       dsc_common_caps->slice_caps.bits.NUM_SLICES_1 =
+               dsc_sink_caps->slice_caps1.bits.NUM_SLICES_1 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_1;
+       dsc_common_caps->slice_caps.bits.NUM_SLICES_2 =
+               dsc_sink_caps->slice_caps1.bits.NUM_SLICES_2 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_2;
+       dsc_common_caps->slice_caps.bits.NUM_SLICES_4 =
+               dsc_sink_caps->slice_caps1.bits.NUM_SLICES_4 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_4;
+       dsc_common_caps->slice_caps.bits.NUM_SLICES_8 =
+               dsc_sink_caps->slice_caps1.bits.NUM_SLICES_8 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_8;
        if (!dsc_common_caps->slice_caps.raw)
                return false;
 
@@ -216,7 +416,8 @@ static bool intersect_dsc_caps(
        if (!dsc_common_caps->lb_bit_depth)
                return false;
 
-       dsc_common_caps->is_block_pred_supported = dsc_sink_caps->is_block_pred_supported && dsc_enc_caps->is_block_pred_supported;
+       dsc_common_caps->is_block_pred_supported =
+               dsc_sink_caps->is_block_pred_supported && dsc_enc_caps->is_block_pred_supported;
 
        dsc_common_caps->color_formats.raw = dsc_sink_caps->color_formats.raw & dsc_enc_caps->color_formats.raw;
        if (!dsc_common_caps->color_formats.raw)
@@ -288,11 +489,11 @@ static struct fixed31_32 compute_dsc_max_bandwidth_overhead(
 }
 
 static uint32_t compute_bpp_x16_from_target_bandwidth(
-               const uint32_t bandwidth_in_kbps,
-               const struct dc_crtc_timing *timing,
-               const uint32_t num_slices_h,
-               const uint32_t bpp_increment_div,
-               const bool is_dp)
+       const uint32_t bandwidth_in_kbps,
+       const struct dc_crtc_timing *timing,
+       const uint32_t num_slices_h,
+       const uint32_t bpp_increment_div,
+       const bool is_dp)
 {
        struct fixed31_32 overhead_in_kbps;
        struct fixed31_32 effective_bandwidth_in_kbps;
@@ -769,146 +970,6 @@ done:
        return is_dsc_possible;
 }
 
-bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, const uint8_t *dpcd_dsc_basic_data, const uint8_t *dpcd_dsc_branch_decoder_caps, struct dsc_dec_dpcd_caps *dsc_sink_caps)
-{
-       if (!dpcd_dsc_basic_data)
-               return false;
-
-       dsc_sink_caps->is_dsc_supported = (dpcd_dsc_basic_data[DP_DSC_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_DECOMPRESSION_IS_SUPPORTED) != 0;
-       if (!dsc_sink_caps->is_dsc_supported)
-               return false;
-
-       dsc_sink_caps->dsc_version = dpcd_dsc_basic_data[DP_DSC_REV - DP_DSC_SUPPORT];
-
-       {
-               int buff_block_size;
-               int buff_size;
-
-               if (!dsc_buff_block_size_from_dpcd(dpcd_dsc_basic_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT], &buff_block_size))
-                       return false;
-
-               buff_size = dpcd_dsc_basic_data[DP_DSC_RC_BUF_SIZE - DP_DSC_SUPPORT] + 1;
-               dsc_sink_caps->rc_buffer_size = buff_size * buff_block_size;
-       }
-
-       dsc_sink_caps->slice_caps1.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_1 - DP_DSC_SUPPORT];
-       if (!dsc_line_buff_depth_from_dpcd(dpcd_dsc_basic_data[DP_DSC_LINE_BUF_BIT_DEPTH - DP_DSC_SUPPORT], &dsc_sink_caps->lb_bit_depth))
-               return false;
-
-       dsc_sink_caps->is_block_pred_supported =
-               (dpcd_dsc_basic_data[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_BLK_PREDICTION_IS_SUPPORTED) != 0;
-
-       dsc_sink_caps->edp_max_bits_per_pixel =
-               dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_LOW - DP_DSC_SUPPORT] |
-               dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] << 8;
-
-       dsc_sink_caps->color_formats.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT];
-       dsc_sink_caps->color_depth.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_DEPTH_CAP - DP_DSC_SUPPORT];
-
-       {
-               int dpcd_throughput = dpcd_dsc_basic_data[DP_DSC_PEAK_THROUGHPUT - DP_DSC_SUPPORT];
-
-               if (!dsc_throughput_from_dpcd(dpcd_throughput & DP_DSC_THROUGHPUT_MODE_0_MASK, &dsc_sink_caps->throughput_mode_0_mps))
-                       return false;
-
-               dpcd_throughput = (dpcd_throughput & DP_DSC_THROUGHPUT_MODE_1_MASK) >> DP_DSC_THROUGHPUT_MODE_1_SHIFT;
-               if (!dsc_throughput_from_dpcd(dpcd_throughput, &dsc_sink_caps->throughput_mode_1_mps))
-                       return false;
-       }
-
-       dsc_sink_caps->max_slice_width = dpcd_dsc_basic_data[DP_DSC_MAX_SLICE_WIDTH - DP_DSC_SUPPORT] * 320;
-       dsc_sink_caps->slice_caps2.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT];
-
-       if (!dsc_bpp_increment_div_from_dpcd(dpcd_dsc_basic_data[DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT], &dsc_sink_caps->bpp_increment_div))
-               return false;
-
-       if (dc->debug.dsc_bpp_increment_div) {
-               /* dsc_bpp_increment_div should onl be 1, 2, 4, 8 or 16, but rather than rejecting invalid values,
-                * we'll accept all and get it into range. This also makes the above check against 0 redundant,
-                * but that one stresses out the override will be only used if it's not 0.
-                */
-               if (dc->debug.dsc_bpp_increment_div >= 1)
-                       dsc_sink_caps->bpp_increment_div = 1;
-               if (dc->debug.dsc_bpp_increment_div >= 2)
-                       dsc_sink_caps->bpp_increment_div = 2;
-               if (dc->debug.dsc_bpp_increment_div >= 4)
-                       dsc_sink_caps->bpp_increment_div = 4;
-               if (dc->debug.dsc_bpp_increment_div >= 8)
-                       dsc_sink_caps->bpp_increment_div = 8;
-               if (dc->debug.dsc_bpp_increment_div >= 16)
-                       dsc_sink_caps->bpp_increment_div = 16;
-       }
-
-       /* Extended caps */
-       if (dpcd_dsc_branch_decoder_caps == NULL) { // branch decoder DPCD DSC data can be null for non branch device
-               dsc_sink_caps->branch_overall_throughput_0_mps = 0;
-               dsc_sink_caps->branch_overall_throughput_1_mps = 0;
-               dsc_sink_caps->branch_max_line_width = 0;
-               return true;
-       }
-
-       dsc_sink_caps->branch_overall_throughput_0_mps = dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_0 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];
-       if (dsc_sink_caps->branch_overall_throughput_0_mps == 0)
-               dsc_sink_caps->branch_overall_throughput_0_mps = 0;
-       else if (dsc_sink_caps->branch_overall_throughput_0_mps == 1)
-               dsc_sink_caps->branch_overall_throughput_0_mps = 680;
-       else {
-               dsc_sink_caps->branch_overall_throughput_0_mps *= 50;
-               dsc_sink_caps->branch_overall_throughput_0_mps += 600;
-       }
-
-       dsc_sink_caps->branch_overall_throughput_1_mps = dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_1 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];
-       if (dsc_sink_caps->branch_overall_throughput_1_mps == 0)
-               dsc_sink_caps->branch_overall_throughput_1_mps = 0;
-       else if (dsc_sink_caps->branch_overall_throughput_1_mps == 1)
-               dsc_sink_caps->branch_overall_throughput_1_mps = 680;
-       else {
-               dsc_sink_caps->branch_overall_throughput_1_mps *= 50;
-               dsc_sink_caps->branch_overall_throughput_1_mps += 600;
-       }
-
-       dsc_sink_caps->branch_max_line_width = dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_MAX_LINE_WIDTH - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0] * 320;
-       ASSERT(dsc_sink_caps->branch_max_line_width == 0 || dsc_sink_caps->branch_max_line_width >= 5120);
-
-       dsc_sink_caps->is_dp = true;
-       return true;
-}
-
-
-/* If DSC is possbile, get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range and
- * timing's pixel clock and uncompressed bandwidth.
- * If DSC is not possible, leave '*range' untouched.
- */
-bool dc_dsc_compute_bandwidth_range(
-               const struct display_stream_compressor *dsc,
-               uint32_t dsc_min_slice_height_override,
-               uint32_t min_bpp_x16,
-               uint32_t max_bpp_x16,
-               const struct dsc_dec_dpcd_caps *dsc_sink_caps,
-               const struct dc_crtc_timing *timing,
-               struct dc_dsc_bw_range *range)
-{
-       bool is_dsc_possible = false;
-       struct dsc_enc_caps dsc_enc_caps;
-       struct dsc_enc_caps dsc_common_caps;
-       struct dc_dsc_config config;
-
-       get_dsc_enc_caps(dsc, &dsc_enc_caps, timing->pix_clk_100hz);
-
-       is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, &dsc_enc_caps,
-                       timing->pixel_encoding, &dsc_common_caps);
-
-       if (is_dsc_possible)
-               is_dsc_possible = setup_dsc_config(dsc_sink_caps, &dsc_enc_caps, 0, timing,
-                               dsc_min_slice_height_override, max_bpp_x16, &config);
-
-       if (is_dsc_possible)
-               get_dsc_bandwidth_range(min_bpp_x16, max_bpp_x16,
-                               config.num_slices_h, &dsc_common_caps, timing, range);
-
-       return is_dsc_possible;
-}
-
 bool dc_dsc_compute_config(
                const struct display_stream_compressor *dsc,
                const struct dsc_dec_dpcd_caps *dsc_sink_caps,
@@ -923,22 +984,22 @@ bool dc_dsc_compute_config(
 
        get_dsc_enc_caps(dsc, &dsc_enc_caps, timing->pix_clk_100hz);
        is_dsc_possible = setup_dsc_config(dsc_sink_caps,
-                       &dsc_enc_caps,
-                       target_bandwidth_kbps,
-                       timing, dsc_min_slice_height_override,
-                       max_target_bpp_limit_override * 16, dsc_cfg);
+               &dsc_enc_caps,
+               target_bandwidth_kbps,
+               timing, dsc_min_slice_height_override,
+               max_target_bpp_limit_override * 16, dsc_cfg);
        return is_dsc_possible;
 }
 
 uint32_t dc_dsc_stream_bandwidth_in_kbps(const struct dc_crtc_timing *timing,
-               uint32_t bpp_x16, uint32_t num_slices_h, bool is_dp)
+       uint32_t bpp_x16, uint32_t num_slices_h, bool is_dp)
 {
        struct fixed31_32 overhead_in_kbps;
        struct fixed31_32 bpp;
        struct fixed31_32 actual_bandwidth_in_kbps;
 
        overhead_in_kbps = compute_dsc_max_bandwidth_overhead(
-                       timing, num_slices_h, is_dp);
+               timing, num_slices_h, is_dp);
        bpp = dc_fixpt_from_fraction(bpp_x16, 16);
        actual_bandwidth_in_kbps = dc_fixpt_from_fraction(timing->pix_clk_100hz, 10);
        actual_bandwidth_in_kbps = dc_fixpt_mul(actual_bandwidth_in_kbps, bpp);
@@ -946,7 +1007,9 @@ uint32_t dc_dsc_stream_bandwidth_in_kbps(const struct dc_crtc_timing *timing,
        return dc_fixpt_ceil(actual_bandwidth_in_kbps);
 }
 
-void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, uint32_t max_target_bpp_limit_override_x16, struct dc_dsc_policy *policy)
+void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing,
+               uint32_t max_target_bpp_limit_override_x16,
+               struct dc_dsc_policy *policy)
 {
        uint32_t bpc = 0;
 
index e2b58ec9912df8590303f3aba1d9aac854e0c765..01c3a31be191a1bfdd887641649260e676aabe69 100644 (file)
@@ -174,7 +174,6 @@ bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable);
 void dp_decide_training_settings(
        struct dc_link *link,
        const struct dc_link_settings *link_setting,
-       const struct dc_link_training_overrides *overrides,
        struct link_training_settings *lt_settings);
 
 /* Convert PHY repeater count read from DPCD uint8_t. */
index 316301fc1e305eeb17eb24c29e11253f50fa3b50..a262f3278c214610f20a68060d354d7833a47953 100644 (file)
@@ -318,6 +318,11 @@ static inline bool should_update_pstate_support(bool safe_to_lower, bool calc_su
        return false;
 }
 
+static inline int khz_to_mhz_ceil(int khz)
+{
+       return (khz + 999) / 1000;
+}
+
 int clk_mgr_helper_get_active_display_cnt(
                struct dc *dc,
                struct dc_state *context);
index 0638b337f14368d68734e308f7bae588c5ab7813..713f5558f5e17cbbc01ccdcecac83f6cbc5c0143 100644 (file)
@@ -102,6 +102,15 @@ struct hubbub_addr_config {
        } default_addrs;
 };
 
+struct dcn_hubbub_state {
+       uint32_t vm_fault_addr_msb;
+       uint32_t vm_fault_addr_lsb;
+       uint32_t vm_error_status;
+       uint32_t vm_error_vmid;
+       uint32_t vm_error_pipe;
+       uint32_t vm_error_mode;
+};
+
 struct hubbub_funcs {
        void (*update_dchub)(
                        struct hubbub *hubbub,
@@ -149,6 +158,8 @@ struct hubbub_funcs {
 
        void (*force_wm_propagate_to_pipes)(struct hubbub *hubbub);
 
+       void (*hubbub_read_state)(struct hubbub *hubbub, struct dcn_hubbub_state *hubbub_state);
+
        void (*force_pstate_change_control)(struct hubbub *hubbub, bool force, bool allow);
 
        void (*init_watermarks)(struct hubbub *hubbub);
index d4d52ef1b165563ee536d0a3ef01808b960564fc..3f12b1600d2afc3a648b5b0abc46110bd6f6623f 100644 (file)
@@ -1,3 +1,28 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
 #ifndef __LINK_DPCD_H__
 #define __LINK_DPCD_H__
 #include <inc/core_status.h>
index 1139b9eb9f6f890d70d7e170c3a81b34e8361bdf..530c2578db406d68e7db326c6dc053b21ba49eb0 100644 (file)
@@ -152,7 +152,7 @@ enum dc_irq_source {
        DC_IRQ_SOURCE_DC6_VLINE1,
        DC_IRQ_SOURCE_DMCUB_OUTBOX,
        DC_IRQ_SOURCE_DMCUB_OUTBOX0,
-
+       DC_IRQ_SOURCE_DMCUB_GENERAL_DATAOUT,
        DAL_IRQ_SOURCES_NUMBER
 };
 
index abbf7ae584c93d9196efe95719f6c03e1b979462..caf961bb633f60f80131d4dad147bd50389b9916 100644 (file)
@@ -352,6 +352,8 @@ struct dmub_srv_hw_funcs {
 
        uint32_t (*get_gpint_response)(struct dmub_srv *dmub);
 
+       uint32_t (*get_gpint_dataout)(struct dmub_srv *dmub);
+
        void (*send_inbox0_cmd)(struct dmub_srv *dmub, union dmub_inbox0_data_register data);
        uint32_t (*get_current_time)(struct dmub_srv *dmub);
 
@@ -676,6 +678,22 @@ dmub_srv_send_gpint_command(struct dmub_srv *dmub,
 enum dmub_status dmub_srv_get_gpint_response(struct dmub_srv *dmub,
                                             uint32_t *response);
 
+/**
+ * dmub_srv_get_gpint_dataout() - Queries the GPINT DATAOUT.
+ * @dmub: the dmub service
+ * @dataout: the data for the GPINT DATAOUT
+ *
+ * Returns the response code for the last GPINT DATAOUT interrupt.
+ *
+ * Can be called after software initialization.
+ *
+ * Return:
+ *   DMUB_STATUS_OK - success
+ *   DMUB_STATUS_INVALID - unspecified error
+ */
+enum dmub_status dmub_srv_get_gpint_dataout(struct dmub_srv *dmub,
+                                            uint32_t *dataout);
+
 /**
  * dmub_flush_buffer_mem() - Read back entire frame buffer region.
  * This ensures that the write from x86 has been flushed and will not
index 7c4734f905d921ba105b9dd657a33b76d818bfc4..02921ad22310e239d6199abbf5fc54acc9b34fc8 100644 (file)
@@ -23,8 +23,8 @@
  *
  */
 
-#ifndef _DMUB_CMD_H_
-#define _DMUB_CMD_H_
+#ifndef DMUB_CMD_H
+#define DMUB_CMD_H
 
 #if defined(_TEST_HARNESS) || defined(FPGA_USB4)
 #include "dmub_fw_types.h"
 
 /* Firmware versioning. */
 #ifdef DMUB_EXPOSE_VERSION
-#define DMUB_FW_VERSION_GIT_HASH 0xf3da2b656
+#define DMUB_FW_VERSION_GIT_HASH 0xe599e0896
 #define DMUB_FW_VERSION_MAJOR 0
 #define DMUB_FW_VERSION_MINOR 0
-#define DMUB_FW_VERSION_REVISION 71
+#define DMUB_FW_VERSION_REVISION 76
 #define DMUB_FW_VERSION_TEST 0
 #define DMUB_FW_VERSION_VBIOS 0
 #define DMUB_FW_VERSION_HOTFIX 0
@@ -334,6 +334,7 @@ enum dmub_fw_boot_status_bit {
        DMUB_FW_BOOT_STATUS_BIT_MAILBOX_READY = (1 << 1), /**< 1 if mailbox ready */
        DMUB_FW_BOOT_STATUS_BIT_OPTIMIZED_INIT_DONE = (1 << 2), /**< 1 if init done */
        DMUB_FW_BOOT_STATUS_BIT_RESTORE_REQUIRED = (1 << 3), /**< 1 if driver should call restore */
+       DMUB_FW_BOOT_STATUS_BIT_DEFERRED_LOADED = (1 << 4), /**< 1 if VBIOS data is deferred programmed */
 };
 
 /* Register bit definition for SCRATCH5 */
@@ -352,7 +353,7 @@ enum dmub_lvtma_status_bit {
 };
 
 /**
- * union dmub_fw_boot_options - Boot option definitions for SCRATCH15
+ * union dmub_fw_boot_options - Boot option definitions for SCRATCH14
  */
 union dmub_fw_boot_options {
        struct {
@@ -363,7 +364,10 @@ union dmub_fw_boot_options {
                uint32_t disable_clk_gate: 1; /**< 1 if clock gating should be disabled */
                uint32_t skip_phy_init_panel_sequence: 1; /**< 1 to skip panel init seq */
                uint32_t z10_disable: 1; /**< 1 to disable z10 */
-               uint32_t reserved : 25; /**< reserved */
+               uint32_t reserved2: 1; /**< reserved for an unreleased feature */
+               uint32_t reserved_unreleased1: 1; /**< reserved for an unreleased feature */
+               uint32_t invalid_vbios_data: 1; /**< 1 if VBIOS data table is invalid */
+               uint32_t reserved : 23; /**< reserved */
        } bits; /**< boot bits */
        uint32_t all; /**< 32-bit access to bits */
 };
@@ -1406,6 +1410,10 @@ struct dmub_cmd_psr_copy_settings_data {
         * Currently the support is only for 0 or 1
         */
        uint8_t panel_inst;
+       /**
+        * Explicit padding to 4 byte boundary.
+        */
+       uint8_t pad3[4];
 };
 
 /**
@@ -2462,16 +2470,14 @@ static inline bool dmub_rb_full(struct dmub_rb *rb)
 static inline bool dmub_rb_push_front(struct dmub_rb *rb,
                                      const union dmub_rb_cmd *cmd)
 {
-       uint64_t volatile *dst = (uint64_t volatile *)(rb->base_address) + rb->wrpt / sizeof(uint64_t);
-       const uint64_t *src = (const uint64_t *)cmd;
-       uint8_t i;
+       uint8_t *dst = (uint8_t *)(rb->base_address) + rb->wrpt;
+       const uint8_t *src = (const uint8_t *)cmd;
 
        if (dmub_rb_full(rb))
                return false;
 
        // copying data
-       for (i = 0; i < DMUB_RB_CMD_SIZE / sizeof(uint64_t); i++)
-               *dst++ = *src++;
+       dmub_memcpy(dst, src, DMUB_RB_CMD_SIZE);
 
        rb->wrpt += DMUB_RB_CMD_SIZE;
 
@@ -2493,7 +2499,7 @@ static inline bool dmub_rb_out_push_front(struct dmub_rb *rb,
                                      const union dmub_rb_out_cmd *cmd)
 {
        uint8_t *dst = (uint8_t *)(rb->base_address) + rb->wrpt;
-       const uint8_t *src = (uint8_t *)cmd;
+       const uint8_t *src = (const uint8_t *)cmd;
 
        if (dmub_rb_full(rb))
                return false;
@@ -2578,18 +2584,16 @@ static inline bool dmub_rb_peek_offset(struct dmub_rb *rb,
  * @return false otherwise
  */
 static inline bool dmub_rb_out_front(struct dmub_rb *rb,
-                                union dmub_rb_out_cmd  *cmd)
+                                union dmub_rb_out_cmd *cmd)
 {
-       const uint64_t volatile *src = (const uint64_t volatile *)(rb->base_address) + rb->rptr / sizeof(uint64_t);
-       uint64_t *dst = (uint64_t *)cmd;
-       uint8_t i;
+       const uint8_t *src = (const uint8_t *)(rb->base_address) + rb->rptr;
+       uint8_t *dst = (uint8_t *)cmd;
 
        if (dmub_rb_empty(rb))
                return false;
 
        // copying data
-       for (i = 0; i < DMUB_RB_CMD_SIZE / sizeof(uint64_t); i++)
-               *dst++ = *src++;
+       dmub_memcpy(dst, src, DMUB_RB_CMD_SIZE);
 
        return true;
 }
@@ -2624,15 +2628,14 @@ static inline bool dmub_rb_pop_front(struct dmub_rb *rb)
  */
 static inline void dmub_rb_flush_pending(const struct dmub_rb *rb)
 {
+       uint8_t buf[DMUB_RB_CMD_SIZE];
        uint32_t rptr = rb->rptr;
        uint32_t wptr = rb->wrpt;
 
        while (rptr != wptr) {
-               uint64_t volatile *data = (uint64_t volatile *)rb->base_address + rptr / sizeof(uint64_t);
-               uint8_t i;
+               const uint8_t *data = (const uint8_t *)rb->base_address + rptr;
 
-               for (i = 0; i < DMUB_RB_CMD_SIZE / sizeof(uint64_t); i++)
-                       *data++;
+               dmub_memcpy(buf, data, DMUB_RB_CMD_SIZE);
 
                rptr += DMUB_RB_CMD_SIZE;
                if (rptr >= rb->capacity)
index 973de346410d37b4c33b9d28c6345b68a09bc653..61446170056eb12fcf3e6eb0089f5e27b23a1760 100644 (file)
 
 const struct dmub_srv_dcn31_regs dmub_srv_dcn31_regs = {
 #define DMUB_SR(reg) REG_OFFSET_EXP(reg),
-       { DMUB_DCN31_REGS() },
+       {
+               DMUB_DCN31_REGS()
+               DMCUB_INTERNAL_REGS()
+       },
 #undef DMUB_SR
 
 #define DMUB_SF(reg, field) FD_MASK(reg, field),
@@ -305,6 +308,21 @@ uint32_t dmub_dcn31_get_gpint_response(struct dmub_srv *dmub)
        return REG_READ(DMCUB_SCRATCH7);
 }
 
+uint32_t dmub_dcn31_get_gpint_dataout(struct dmub_srv *dmub)
+{
+       uint32_t dataout = REG_READ(DMCUB_GPINT_DATAOUT);
+
+       REG_UPDATE(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN, 0);
+
+       REG_WRITE(DMCUB_GPINT_DATAOUT, 0);
+       REG_UPDATE(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK, 1);
+       REG_UPDATE(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK, 0);
+
+       REG_UPDATE(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN, 1);
+
+       return dataout;
+}
+
 union dmub_fw_boot_status dmub_dcn31_get_fw_boot_status(struct dmub_srv *dmub)
 {
        union dmub_fw_boot_status status;
index 9456a6a2d51841d6263e9520162b2cd23082fcd9..bb62605d2ac8927382241e6caa546e2dbcc5a7a2 100644 (file)
@@ -114,7 +114,9 @@ struct dmub_srv;
        DMUB_SR(DMCUB_TIMER_CURRENT) \
        DMUB_SR(DMCUB_INST_FETCH_FAULT_ADDR) \
        DMUB_SR(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR) \
-       DMUB_SR(DMCUB_DATA_WRITE_FAULT_ADDR)
+       DMUB_SR(DMCUB_DATA_WRITE_FAULT_ADDR) \
+       DMUB_SR(DMCUB_INTERRUPT_ENABLE) \
+       DMUB_SR(DMCUB_INTERRUPT_ACK)
 
 #define DMUB_DCN31_FIELDS() \
        DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \
@@ -147,7 +149,9 @@ struct dmub_srv;
        DMUB_SF(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET) \
        DMUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE) \
        DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET) \
-       DMUB_SF(DMCUB_INBOX0_WPTR, DMCUB_INBOX0_WPTR)
+       DMUB_SF(DMCUB_INBOX0_WPTR, DMCUB_INBOX0_WPTR) \
+       DMUB_SF(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN) \
+       DMUB_SF(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK)
 
 struct dmub_srv_dcn31_reg_offset {
 #define DMUB_SR(reg) uint32_t reg;
@@ -222,6 +226,8 @@ bool dmub_dcn31_is_gpint_acked(struct dmub_srv *dmub,
 
 uint32_t dmub_dcn31_get_gpint_response(struct dmub_srv *dmub);
 
+uint32_t dmub_dcn31_get_gpint_dataout(struct dmub_srv *dmub);
+
 void dmub_dcn31_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params);
 
 void dmub_dcn31_skip_dmub_panel_power_sequence(struct dmub_srv *dmub, bool skip);
index 2bdbd7406f5655015d1a485b8dc919ad479e04e1..75a91cfaf03602c2589fa3118d6791a12c71a042 100644 (file)
@@ -224,6 +224,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
                funcs->set_gpint = dmub_dcn31_set_gpint;
                funcs->is_gpint_acked = dmub_dcn31_is_gpint_acked;
                funcs->get_gpint_response = dmub_dcn31_get_gpint_response;
+               funcs->get_gpint_dataout = dmub_dcn31_get_gpint_dataout;
                funcs->get_fw_status = dmub_dcn31_get_fw_boot_status;
                funcs->enable_dmub_boot_options = dmub_dcn31_enable_dmub_boot_options;
                funcs->skip_dmub_panel_power_sequence = dmub_dcn31_skip_dmub_panel_power_sequence;
@@ -719,6 +720,22 @@ enum dmub_status dmub_srv_get_gpint_response(struct dmub_srv *dmub,
        return DMUB_STATUS_OK;
 }
 
+enum dmub_status dmub_srv_get_gpint_dataout(struct dmub_srv *dmub,
+                                            uint32_t *dataout)
+{
+       *dataout = 0;
+
+       if (!dmub->sw_init)
+               return DMUB_STATUS_INVALID;
+
+       if (!dmub->hw_funcs.get_gpint_dataout)
+               return DMUB_STATUS_INVALID;
+
+       *dataout = dmub->hw_funcs.get_gpint_dataout(dmub);
+
+       return DMUB_STATUS_OK;
+}
+
 enum dmub_status dmub_srv_get_fw_boot_status(struct dmub_srv *dmub,
                                             union dmub_fw_boot_status *status)
 {
index b963226e8af433d855ef0f6296ee30814ad6c4fe..06d60f031a0680bf799035697ad2fb654e8c2498 100644 (file)
@@ -39,8 +39,12 @@ static void push_error_status(struct mod_hdcp *hdcp,
 
        if (is_hdcp1(hdcp)) {
                hdcp->connection.hdcp1_retry_count++;
+               if (hdcp->connection.hdcp1_retry_count == MAX_NUM_OF_ATTEMPTS)
+                       hdcp->connection.link.adjust.hdcp1.disable = 1;
        } else if (is_hdcp2(hdcp)) {
                hdcp->connection.hdcp2_retry_count++;
+               if (hdcp->connection.hdcp2_retry_count == MAX_NUM_OF_ATTEMPTS)
+                       hdcp->connection.link.adjust.hdcp2.disable = 1;
        }
 }
 
@@ -59,8 +63,7 @@ static uint8_t is_cp_desired_hdcp1(struct mod_hdcp *hdcp)
                }
        }
 
-       return (hdcp->connection.hdcp1_retry_count < MAX_NUM_OF_ATTEMPTS) &&
-                       is_auth_needed &&
+       return is_auth_needed &&
                        !hdcp->connection.link.adjust.hdcp1.disable &&
                        !hdcp->connection.is_hdcp1_revoked;
 }
@@ -80,8 +83,7 @@ static uint8_t is_cp_desired_hdcp2(struct mod_hdcp *hdcp)
                }
        }
 
-       return (hdcp->connection.hdcp2_retry_count < MAX_NUM_OF_ATTEMPTS) &&
-                       is_auth_needed &&
+       return is_auth_needed &&
                        !hdcp->connection.link.adjust.hdcp2.disable &&
                        !hdcp->connection.is_hdcp2_revoked;
 }
@@ -313,9 +315,6 @@ enum mod_hdcp_status mod_hdcp_add_display(struct mod_hdcp *hdcp,
                goto out;
        }
 
-       /* save current encryption states to restore after next authentication */
-       mod_hdcp_save_current_encryption_states(hdcp);
-
        /* reset existing authentication status */
        status = reset_authentication(hdcp, output);
        if (status != MOD_HDCP_STATUS_SUCCESS)
@@ -362,9 +361,6 @@ enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp,
                goto out;
        }
 
-       /* save current encryption states to restore after next authentication */
-       mod_hdcp_save_current_encryption_states(hdcp);
-
        /* stop current authentication */
        status = reset_authentication(hdcp, output);
        if (status != MOD_HDCP_STATUS_SUCCESS)
@@ -392,6 +388,60 @@ out:
        return status;
 }
 
+enum mod_hdcp_status mod_hdcp_update_authentication(struct mod_hdcp *hdcp,
+               uint8_t index,
+               struct mod_hdcp_link_adjustment *link_adjust,
+               struct mod_hdcp_display_adjustment *display_adjust,
+               struct mod_hdcp_output *output)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+       struct mod_hdcp_display *display = NULL;
+
+       HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, index);
+       memset(output, 0, sizeof(struct mod_hdcp_output));
+
+       /* find display in connection */
+       display = get_active_display_at_index(hdcp, index);
+       if (!display) {
+               status = MOD_HDCP_STATUS_DISPLAY_NOT_FOUND;
+               goto out;
+       }
+
+       /* skip if no changes */
+       if (memcmp(link_adjust, &hdcp->connection.link.adjust,
+                       sizeof(struct mod_hdcp_link_adjustment)) == 0 &&
+                       memcmp(display_adjust, &display->adjust,
+                                       sizeof(struct mod_hdcp_display_adjustment)) == 0) {
+               status = MOD_HDCP_STATUS_SUCCESS;
+               goto out;
+       }
+
+       /* stop current authentication */
+       status = reset_authentication(hdcp, output);
+       if (status != MOD_HDCP_STATUS_SUCCESS)
+               goto out;
+
+       /* clear retry counters */
+       reset_retry_counts(hdcp);
+
+       /* reset error trace */
+       memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace));
+
+       /* set new adjustment */
+       hdcp->connection.link.adjust = *link_adjust;
+       display->adjust = *display_adjust;
+
+       /* request authentication when connection is not reset */
+       if (current_state(hdcp) != HDCP_UNINITIALIZED)
+               /* wait 100ms to debounce simultaneous updates for different indices */
+               callback_in_ms(100, output);
+
+out:
+       if (status != MOD_HDCP_STATUS_SUCCESS)
+               push_error_status(hdcp, status);
+       return status;
+}
+
 enum mod_hdcp_status mod_hdcp_query_display(struct mod_hdcp *hdcp,
                uint8_t index, struct mod_hdcp_display_query *query)
 {
index 3ce91db560d1d2224025109719b6e8e221e105a5..7123f0915706cd721c9e309533465dedaa1dc40e 100644 (file)
@@ -331,8 +331,6 @@ enum mod_hdcp_status mod_hdcp_add_display_to_topology(
                struct mod_hdcp *hdcp, struct mod_hdcp_display *display);
 enum mod_hdcp_status mod_hdcp_remove_display_from_topology(
                struct mod_hdcp *hdcp, uint8_t index);
-bool mod_hdcp_is_link_encryption_enabled(struct mod_hdcp *hdcp);
-void mod_hdcp_save_current_encryption_states(struct mod_hdcp *hdcp);
 enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp);
 enum mod_hdcp_status mod_hdcp_hdcp1_destroy_session(struct mod_hdcp *hdcp);
 enum mod_hdcp_status mod_hdcp_hdcp1_validate_rx(struct mod_hdcp *hdcp);
index de872e7958b0657f61605f261f9eb2fd5400826b..6ec918af3bffc764f669d5bf166ca5e0ba349441 100644 (file)
@@ -266,9 +266,6 @@ static enum mod_hdcp_status authenticated(struct mod_hdcp *hdcp,
        mod_hdcp_execute_and_set(mod_hdcp_hdcp1_link_maintenance,
                        &input->link_maintenance, &status,
                        hdcp, "link_maintenance");
-
-       if (status != MOD_HDCP_STATUS_SUCCESS)
-               mod_hdcp_save_current_encryption_states(hdcp);
 out:
        return status;
 }
@@ -447,9 +444,6 @@ static enum mod_hdcp_status authenticated_dp(struct mod_hdcp *hdcp,
                mod_hdcp_execute_and_set(check_no_reauthentication_request_dp,
                                &input->reauth_request_check, &status,
                                hdcp, "reauth_request_check");
-
-       if (status != MOD_HDCP_STATUS_SUCCESS)
-               mod_hdcp_save_current_encryption_states(hdcp);
 out:
        return status;
 }
index 117c6b45f71891bcc5786dc0f4152e82ccc457bd..91c22b96ebde7fc5446e78f2557ac3bb33b56020 100644 (file)
@@ -571,9 +571,6 @@ static enum mod_hdcp_status authenticated(struct mod_hdcp *hdcp,
        }
 
        process_rxstatus(hdcp, event_ctx, input, &status);
-
-       if (status != MOD_HDCP_STATUS_SUCCESS)
-               mod_hdcp_save_current_encryption_states(hdcp);
 out:
        return status;
 }
index 1b02056bc8bdeff57e7d3e9bbddee55eae61207e..ade86a042398fbdca0cf183dd6a6b74664d4e991 100644 (file)
@@ -45,7 +45,7 @@ static void hdcp2_message_init(struct mod_hdcp *hdcp,
        in->process.msg3_desc.msg_size = 0;
 }
 
-static enum mod_hdcp_status mod_hdcp_remove_display_from_topology_v2(
+static enum mod_hdcp_status remove_display_from_topology_v2(
                struct mod_hdcp *hdcp, uint8_t index)
 {
        struct psp_context *psp = hdcp->config.psp.handle;
@@ -81,7 +81,7 @@ static enum mod_hdcp_status mod_hdcp_remove_display_from_topology_v2(
        return status;
 }
 
-static enum mod_hdcp_status mod_hdcp_remove_display_from_topology_v3(
+static enum mod_hdcp_status remove_display_from_topology_v3(
                struct mod_hdcp *hdcp, uint8_t index)
 {
        struct psp_context *psp = hdcp->config.psp.handle;
@@ -107,7 +107,7 @@ static enum mod_hdcp_status mod_hdcp_remove_display_from_topology_v3(
        psp_dtm_invoke(psp, dtm_cmd->cmd_id);
 
        if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) {
-               status = mod_hdcp_remove_display_from_topology_v2(hdcp, index);
+               status = remove_display_from_topology_v2(hdcp, index);
                if (status != MOD_HDCP_STATUS_SUCCESS)
                        display->state = MOD_HDCP_DISPLAY_INACTIVE;
        } else {
@@ -120,20 +120,7 @@ static enum mod_hdcp_status mod_hdcp_remove_display_from_topology_v3(
        return status;
 }
 
-enum mod_hdcp_status mod_hdcp_remove_display_from_topology(
-               struct mod_hdcp *hdcp, uint8_t index)
-{
-       enum mod_hdcp_status status = MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE;
-
-       if (hdcp->config.psp.caps.dtm_v3_supported)
-               status = mod_hdcp_remove_display_from_topology_v3(hdcp, index);
-       else
-               status = mod_hdcp_remove_display_from_topology_v2(hdcp, index);
-
-       return status;
-}
-
-static enum mod_hdcp_status mod_hdcp_add_display_to_topology_v2(
+static enum mod_hdcp_status add_display_to_topology_v2(
                struct mod_hdcp *hdcp, struct mod_hdcp_display *display)
 {
        struct psp_context *psp = hdcp->config.psp.handle;
@@ -180,7 +167,7 @@ static enum mod_hdcp_status mod_hdcp_add_display_to_topology_v2(
        return status;
 }
 
-static enum mod_hdcp_status mod_hdcp_add_display_to_topology_v3(
+static enum mod_hdcp_status add_display_to_topology_v3(
                struct mod_hdcp *hdcp, struct mod_hdcp_display *display)
 {
        struct psp_context *psp = hdcp->config.psp.handle;
@@ -220,7 +207,7 @@ static enum mod_hdcp_status mod_hdcp_add_display_to_topology_v3(
        psp_dtm_invoke(psp, dtm_cmd->cmd_id);
 
        if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) {
-               status = mod_hdcp_add_display_to_topology_v2(hdcp, display);
+               status = add_display_to_topology_v2(hdcp, display);
                if (status != MOD_HDCP_STATUS_SUCCESS)
                        display->state = MOD_HDCP_DISPLAY_INACTIVE;
        } else {
@@ -232,15 +219,28 @@ static enum mod_hdcp_status mod_hdcp_add_display_to_topology_v3(
        return status;
 }
 
+enum mod_hdcp_status mod_hdcp_remove_display_from_topology(
+               struct mod_hdcp *hdcp, uint8_t index)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE;
+
+       if (hdcp->config.psp.caps.dtm_v3_supported)
+               status = remove_display_from_topology_v3(hdcp, index);
+       else
+               status = remove_display_from_topology_v2(hdcp, index);
+
+       return status;
+}
+
 enum mod_hdcp_status mod_hdcp_add_display_to_topology(struct mod_hdcp *hdcp,
                                               struct mod_hdcp_display *display)
 {
        enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
 
        if (hdcp->config.psp.caps.dtm_v3_supported)
-               status = mod_hdcp_add_display_to_topology_v3(hdcp, display);
+               status = add_display_to_topology_v3(hdcp, display);
        else
-               status = mod_hdcp_add_display_to_topology_v2(hdcp, display);
+               status = add_display_to_topology_v2(hdcp, display);
 
        return status;
 }
@@ -1021,14 +1021,3 @@ enum mod_hdcp_status mod_hdcp_hdcp2_validate_stream_ready(struct mod_hdcp *hdcp)
        mutex_unlock(&psp->hdcp_context.mutex);
        return status;
 }
-
-bool mod_hdcp_is_link_encryption_enabled(struct mod_hdcp *hdcp)
-{
-       /* unsupported */
-       return true;
-}
-
-void mod_hdcp_save_current_encryption_states(struct mod_hdcp *hdcp)
-{
-       /* unsupported */
-}
index c590493fd2936c36e1ad6ff16d87d271ca9b7e83..a6eb86de8d5c77ffbd863a2c1ea6f52a86c4cec1 100644 (file)
@@ -123,7 +123,6 @@ enum mod_hdcp_display_state {
 
 struct mod_hdcp_psp_caps {
        uint8_t dtm_v3_supported;
-       uint8_t opm_state_query_supported;
 };
 
 enum mod_hdcp_display_disable_option {
@@ -282,15 +281,22 @@ enum mod_hdcp_status mod_hdcp_setup(struct mod_hdcp *hdcp,
 /* called per link on link destroy */
 enum mod_hdcp_status mod_hdcp_teardown(struct mod_hdcp *hdcp);
 
-/* called per display on cp_desired set to true */
+/* called per display after stream is enabled */
 enum mod_hdcp_status mod_hdcp_add_display(struct mod_hdcp *hdcp,
                struct mod_hdcp_link *link, struct mod_hdcp_display *display,
                struct mod_hdcp_output *output);
 
-/* called per display on cp_desired set to false */
+/* called per display before stream is disabled */
 enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp,
                uint8_t index, struct mod_hdcp_output *output);
 
+/* called per display to apply new authentication adjustment */
+enum mod_hdcp_status mod_hdcp_update_authentication(struct mod_hdcp *hdcp,
+               uint8_t index,
+               struct mod_hdcp_link_adjustment *link_adjust,
+               struct mod_hdcp_display_adjustment *display_adjust,
+               struct mod_hdcp_output *output);
+
 /* called to query hdcp information on a specific index */
 enum mod_hdcp_status mod_hdcp_query_display(struct mod_hdcp *hdcp,
                uint8_t index, struct mod_hdcp_display_query *query);
index ff1d3d4a6488940e7598bdd07d6f9a0e9461946d..257f280d3d53fed0175a504edcc4fa05830683bd 100644 (file)
@@ -47,6 +47,7 @@ enum amd_apu_flags {
        AMD_APU_IS_RENOIR = 0x00000008UL,
        AMD_APU_IS_GREEN_SARDINE = 0x00000010UL,
        AMD_APU_IS_VANGOGH = 0x00000020UL,
+       AMD_APU_IS_CYAN_SKILLFISH2 = 0x00000040UL,
 };
 
 /**
index e5fd0121ceff80e87ac33b9c0fb8e1c7bd386cb4..a9d553ef26c0009edb69bafdced1ad410f230d88 100644 (file)
 #define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT1_INT_EN__SHIFT                                                    0xb
 #define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT2_INT_EN__SHIFT                                                    0xc
 #define DMCUB_INTERRUPT_ENABLE__DMCUB_UNDEFINED_ADDRESS_FAULT_INT_EN__SHIFT                                   0xd
+#define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT_IH_INT_EN__SHIFT                                                  0x11
 #define DMCUB_INTERRUPT_ENABLE__DMCUB_TIMER0_INT_EN_MASK                                                      0x00000001L
 #define DMCUB_INTERRUPT_ENABLE__DMCUB_TIMER1_INT_EN_MASK                                                      0x00000002L
 #define DMCUB_INTERRUPT_ENABLE__DMCUB_INBOX0_READY_INT_EN_MASK                                                0x00000004L
 #define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT1_INT_EN_MASK                                                      0x00000800L
 #define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT2_INT_EN_MASK                                                      0x00001000L
 #define DMCUB_INTERRUPT_ENABLE__DMCUB_UNDEFINED_ADDRESS_FAULT_INT_EN_MASK                                     0x00002000L
+#define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT_IH_INT_EN_MASK                                                    0x00020000L
 //DMCUB_INTERRUPT_ACK
 #define DMCUB_INTERRUPT_ACK__DMCUB_TIMER0_INT_ACK__SHIFT                                                      0x0
 #define DMCUB_INTERRUPT_ACK__DMCUB_TIMER1_INT_ACK__SHIFT                                                      0x1
 #define DMCUB_INTERRUPT_ACK__DMCUB_GPINT1_INT_ACK__SHIFT                                                      0xb
 #define DMCUB_INTERRUPT_ACK__DMCUB_GPINT2_INT_ACK__SHIFT                                                      0xc
 #define DMCUB_INTERRUPT_ACK__DMCUB_UNDEFINED_ADDRESS_FAULT_ACK__SHIFT                                         0xd
+#define DMCUB_INTERRUPT_ACK__DMCUB_GPINT_IH_INT_ACK__SHIFT                                                    0x11
 #define DMCUB_INTERRUPT_ACK__DMCUB_TIMER0_INT_ACK_MASK                                                        0x00000001L
 #define DMCUB_INTERRUPT_ACK__DMCUB_TIMER1_INT_ACK_MASK                                                        0x00000002L
 #define DMCUB_INTERRUPT_ACK__DMCUB_INBOX0_READY_INT_ACK_MASK                                                  0x00000004L
 #define DMCUB_INTERRUPT_ACK__DMCUB_GPINT1_INT_ACK_MASK                                                        0x00000800L
 #define DMCUB_INTERRUPT_ACK__DMCUB_GPINT2_INT_ACK_MASK                                                        0x00001000L
 #define DMCUB_INTERRUPT_ACK__DMCUB_UNDEFINED_ADDRESS_FAULT_ACK_MASK                                           0x00002000L
+#define DMCUB_INTERRUPT_ACK__DMCUB_GPINT_IH_INT_ACK_MASK                                                      0x00020000L
 //DMCUB_INTERRUPT_STATUS
 #define DMCUB_INTERRUPT_STATUS__DMCUB_TIMER0_INT_STAT__SHIFT                                                  0x0
 #define DMCUB_INTERRUPT_STATUS__DMCUB_TIMER1_INT_STAT__SHIFT                                                  0x1
diff --git a/drivers/gpu/drm/amd/include/asic_reg/mp/mp_11_0_8_offset.h b/drivers/gpu/drm/amd/include/asic_reg/mp/mp_11_0_8_offset.h
new file mode 100644 (file)
index 0000000..19293cc
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2021  Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef _mp_11_0_8_OFFSET_HEADER
+#define _mp_11_0_8_OFFSET_HEADER
+
+
+
+// addressBlock: mp_SmuMp0_SmnDec
+// base address: 0x0
+#define mmMP0_SMN_C2PMSG_32                                                                            0x0060
+#define mmMP0_SMN_C2PMSG_32_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_33                                                                            0x0061
+#define mmMP0_SMN_C2PMSG_33_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_34                                                                            0x0062
+#define mmMP0_SMN_C2PMSG_34_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_35                                                                            0x0063
+#define mmMP0_SMN_C2PMSG_35_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_36                                                                            0x0064
+#define mmMP0_SMN_C2PMSG_36_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_37                                                                            0x0065
+#define mmMP0_SMN_C2PMSG_37_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_38                                                                            0x0066
+#define mmMP0_SMN_C2PMSG_38_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_39                                                                            0x0067
+#define mmMP0_SMN_C2PMSG_39_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_40                                                                            0x0068
+#define mmMP0_SMN_C2PMSG_40_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_41                                                                            0x0069
+#define mmMP0_SMN_C2PMSG_41_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_42                                                                            0x006a
+#define mmMP0_SMN_C2PMSG_42_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_43                                                                            0x006b
+#define mmMP0_SMN_C2PMSG_43_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_44                                                                            0x006c
+#define mmMP0_SMN_C2PMSG_44_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_45                                                                            0x006d
+#define mmMP0_SMN_C2PMSG_45_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_46                                                                            0x006e
+#define mmMP0_SMN_C2PMSG_46_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_47                                                                            0x006f
+#define mmMP0_SMN_C2PMSG_47_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_48                                                                            0x0070
+#define mmMP0_SMN_C2PMSG_48_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_49                                                                            0x0071
+#define mmMP0_SMN_C2PMSG_49_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_50                                                                            0x0072
+#define mmMP0_SMN_C2PMSG_50_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_51                                                                            0x0073
+#define mmMP0_SMN_C2PMSG_51_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_52                                                                            0x0074
+#define mmMP0_SMN_C2PMSG_52_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_53                                                                            0x0075
+#define mmMP0_SMN_C2PMSG_53_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_54                                                                            0x0076
+#define mmMP0_SMN_C2PMSG_54_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_55                                                                            0x0077
+#define mmMP0_SMN_C2PMSG_55_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_56                                                                            0x0078
+#define mmMP0_SMN_C2PMSG_56_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_57                                                                            0x0079
+#define mmMP0_SMN_C2PMSG_57_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_58                                                                            0x007a
+#define mmMP0_SMN_C2PMSG_58_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_59                                                                            0x007b
+#define mmMP0_SMN_C2PMSG_59_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_60                                                                            0x007c
+#define mmMP0_SMN_C2PMSG_60_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_61                                                                            0x007d
+#define mmMP0_SMN_C2PMSG_61_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_62                                                                            0x007e
+#define mmMP0_SMN_C2PMSG_62_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_63                                                                            0x007f
+#define mmMP0_SMN_C2PMSG_63_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_64                                                                            0x0080
+#define mmMP0_SMN_C2PMSG_64_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_65                                                                            0x0081
+#define mmMP0_SMN_C2PMSG_65_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_66                                                                            0x0082
+#define mmMP0_SMN_C2PMSG_66_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_67                                                                            0x0083
+#define mmMP0_SMN_C2PMSG_67_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_68                                                                            0x0084
+#define mmMP0_SMN_C2PMSG_68_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_69                                                                            0x0085
+#define mmMP0_SMN_C2PMSG_69_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_70                                                                            0x0086
+#define mmMP0_SMN_C2PMSG_70_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_71                                                                            0x0087
+#define mmMP0_SMN_C2PMSG_71_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_72                                                                            0x0088
+#define mmMP0_SMN_C2PMSG_72_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_73                                                                            0x0089
+#define mmMP0_SMN_C2PMSG_73_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_74                                                                            0x008a
+#define mmMP0_SMN_C2PMSG_74_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_75                                                                            0x008b
+#define mmMP0_SMN_C2PMSG_75_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_76                                                                            0x008c
+#define mmMP0_SMN_C2PMSG_76_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_77                                                                            0x008d
+#define mmMP0_SMN_C2PMSG_77_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_78                                                                            0x008e
+#define mmMP0_SMN_C2PMSG_78_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_79                                                                            0x008f
+#define mmMP0_SMN_C2PMSG_79_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_80                                                                            0x0090
+#define mmMP0_SMN_C2PMSG_80_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_81                                                                            0x0091
+#define mmMP0_SMN_C2PMSG_81_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_82                                                                            0x0092
+#define mmMP0_SMN_C2PMSG_82_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_83                                                                            0x0093
+#define mmMP0_SMN_C2PMSG_83_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_84                                                                            0x0094
+#define mmMP0_SMN_C2PMSG_84_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_85                                                                            0x0095
+#define mmMP0_SMN_C2PMSG_85_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_86                                                                            0x0096
+#define mmMP0_SMN_C2PMSG_86_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_87                                                                            0x0097
+#define mmMP0_SMN_C2PMSG_87_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_88                                                                            0x0098
+#define mmMP0_SMN_C2PMSG_88_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_89                                                                            0x0099
+#define mmMP0_SMN_C2PMSG_89_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_90                                                                            0x009a
+#define mmMP0_SMN_C2PMSG_90_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_91                                                                            0x009b
+#define mmMP0_SMN_C2PMSG_91_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_92                                                                            0x009c
+#define mmMP0_SMN_C2PMSG_92_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_93                                                                            0x009d
+#define mmMP0_SMN_C2PMSG_93_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_94                                                                            0x009e
+#define mmMP0_SMN_C2PMSG_94_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_95                                                                            0x009f
+#define mmMP0_SMN_C2PMSG_95_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_96                                                                            0x00a0
+#define mmMP0_SMN_C2PMSG_96_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_97                                                                            0x00a1
+#define mmMP0_SMN_C2PMSG_97_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_98                                                                            0x00a2
+#define mmMP0_SMN_C2PMSG_98_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_99                                                                            0x00a3
+#define mmMP0_SMN_C2PMSG_99_BASE_IDX                                                                   0
+#define mmMP0_SMN_C2PMSG_100                                                                           0x00a4
+#define mmMP0_SMN_C2PMSG_100_BASE_IDX                                                                  0
+#define mmMP0_SMN_C2PMSG_101                                                                           0x00a5
+#define mmMP0_SMN_C2PMSG_101_BASE_IDX                                                                  0
+#define mmMP0_SMN_C2PMSG_102                                                                           0x00a6
+#define mmMP0_SMN_C2PMSG_102_BASE_IDX                                                                  0
+#define mmMP0_SMN_C2PMSG_103                                                                           0x00a7
+#define mmMP0_SMN_C2PMSG_103_BASE_IDX                                                                  0
+#define mmMP0_SMN_IH_CREDIT                                                                            0x00c1
+#define mmMP0_SMN_IH_CREDIT_BASE_IDX                                                                   0
+#define mmMP0_SMN_IH_SW_INT                                                                            0x00c2
+#define mmMP0_SMN_IH_SW_INT_BASE_IDX                                                                   0
+#define mmMP0_SMN_IH_SW_INT_CTRL                                                                       0x00c3
+#define mmMP0_SMN_IH_SW_INT_CTRL_BASE_IDX                                                              0
+
+
+// addressBlock: mp_SmuMp1_SmnDec
+// base address: 0x0
+#define mmMP1_SMN_C2PMSG_32                                                                            0x0260
+#define mmMP1_SMN_C2PMSG_32_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_33                                                                            0x0261
+#define mmMP1_SMN_C2PMSG_33_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_34                                                                            0x0262
+#define mmMP1_SMN_C2PMSG_34_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_35                                                                            0x0263
+#define mmMP1_SMN_C2PMSG_35_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_36                                                                            0x0264
+#define mmMP1_SMN_C2PMSG_36_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_37                                                                            0x0265
+#define mmMP1_SMN_C2PMSG_37_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_38                                                                            0x0266
+#define mmMP1_SMN_C2PMSG_38_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_39                                                                            0x0267
+#define mmMP1_SMN_C2PMSG_39_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_40                                                                            0x0268
+#define mmMP1_SMN_C2PMSG_40_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_41                                                                            0x0269
+#define mmMP1_SMN_C2PMSG_41_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_42                                                                            0x026a
+#define mmMP1_SMN_C2PMSG_42_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_43                                                                            0x026b
+#define mmMP1_SMN_C2PMSG_43_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_44                                                                            0x026c
+#define mmMP1_SMN_C2PMSG_44_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_45                                                                            0x026d
+#define mmMP1_SMN_C2PMSG_45_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_46                                                                            0x026e
+#define mmMP1_SMN_C2PMSG_46_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_47                                                                            0x026f
+#define mmMP1_SMN_C2PMSG_47_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_48                                                                            0x0270
+#define mmMP1_SMN_C2PMSG_48_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_49                                                                            0x0271
+#define mmMP1_SMN_C2PMSG_49_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_50                                                                            0x0272
+#define mmMP1_SMN_C2PMSG_50_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_51                                                                            0x0273
+#define mmMP1_SMN_C2PMSG_51_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_52                                                                            0x0274
+#define mmMP1_SMN_C2PMSG_52_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_53                                                                            0x0275
+#define mmMP1_SMN_C2PMSG_53_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_54                                                                            0x0276
+#define mmMP1_SMN_C2PMSG_54_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_55                                                                            0x0277
+#define mmMP1_SMN_C2PMSG_55_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_56                                                                            0x0278
+#define mmMP1_SMN_C2PMSG_56_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_57                                                                            0x0279
+#define mmMP1_SMN_C2PMSG_57_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_58                                                                            0x027a
+#define mmMP1_SMN_C2PMSG_58_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_59                                                                            0x027b
+#define mmMP1_SMN_C2PMSG_59_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_60                                                                            0x027c
+#define mmMP1_SMN_C2PMSG_60_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_61                                                                            0x027d
+#define mmMP1_SMN_C2PMSG_61_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_62                                                                            0x027e
+#define mmMP1_SMN_C2PMSG_62_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_63                                                                            0x027f
+#define mmMP1_SMN_C2PMSG_63_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_64                                                                            0x0280
+#define mmMP1_SMN_C2PMSG_64_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_65                                                                            0x0281
+#define mmMP1_SMN_C2PMSG_65_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_66                                                                            0x0282
+#define mmMP1_SMN_C2PMSG_66_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_67                                                                            0x0283
+#define mmMP1_SMN_C2PMSG_67_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_68                                                                            0x0284
+#define mmMP1_SMN_C2PMSG_68_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_69                                                                            0x0285
+#define mmMP1_SMN_C2PMSG_69_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_70                                                                            0x0286
+#define mmMP1_SMN_C2PMSG_70_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_71                                                                            0x0287
+#define mmMP1_SMN_C2PMSG_71_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_72                                                                            0x0288
+#define mmMP1_SMN_C2PMSG_72_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_73                                                                            0x0289
+#define mmMP1_SMN_C2PMSG_73_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_74                                                                            0x028a
+#define mmMP1_SMN_C2PMSG_74_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_75                                                                            0x028b
+#define mmMP1_SMN_C2PMSG_75_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_76                                                                            0x028c
+#define mmMP1_SMN_C2PMSG_76_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_77                                                                            0x028d
+#define mmMP1_SMN_C2PMSG_77_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_78                                                                            0x028e
+#define mmMP1_SMN_C2PMSG_78_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_79                                                                            0x028f
+#define mmMP1_SMN_C2PMSG_79_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_80                                                                            0x0290
+#define mmMP1_SMN_C2PMSG_80_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_81                                                                            0x0291
+#define mmMP1_SMN_C2PMSG_81_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_82                                                                            0x0292
+#define mmMP1_SMN_C2PMSG_82_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_83                                                                            0x0293
+#define mmMP1_SMN_C2PMSG_83_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_84                                                                            0x0294
+#define mmMP1_SMN_C2PMSG_84_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_85                                                                            0x0295
+#define mmMP1_SMN_C2PMSG_85_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_86                                                                            0x0296
+#define mmMP1_SMN_C2PMSG_86_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_87                                                                            0x0297
+#define mmMP1_SMN_C2PMSG_87_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_88                                                                            0x0298
+#define mmMP1_SMN_C2PMSG_88_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_89                                                                            0x0299
+#define mmMP1_SMN_C2PMSG_89_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_90                                                                            0x029a
+#define mmMP1_SMN_C2PMSG_90_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_91                                                                            0x029b
+#define mmMP1_SMN_C2PMSG_91_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_92                                                                            0x029c
+#define mmMP1_SMN_C2PMSG_92_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_93                                                                            0x029d
+#define mmMP1_SMN_C2PMSG_93_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_94                                                                            0x029e
+#define mmMP1_SMN_C2PMSG_94_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_95                                                                            0x029f
+#define mmMP1_SMN_C2PMSG_95_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_96                                                                            0x02a0
+#define mmMP1_SMN_C2PMSG_96_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_97                                                                            0x02a1
+#define mmMP1_SMN_C2PMSG_97_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_98                                                                            0x02a2
+#define mmMP1_SMN_C2PMSG_98_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_99                                                                            0x02a3
+#define mmMP1_SMN_C2PMSG_99_BASE_IDX                                                                   0
+#define mmMP1_SMN_C2PMSG_100                                                                           0x02a4
+#define mmMP1_SMN_C2PMSG_100_BASE_IDX                                                                  0
+#define mmMP1_SMN_C2PMSG_101                                                                           0x02a5
+#define mmMP1_SMN_C2PMSG_101_BASE_IDX                                                                  0
+#define mmMP1_SMN_C2PMSG_102                                                                           0x02a6
+#define mmMP1_SMN_C2PMSG_102_BASE_IDX                                                                  0
+#define mmMP1_SMN_C2PMSG_103                                                                           0x02a7
+#define mmMP1_SMN_C2PMSG_103_BASE_IDX                                                                  0
+#define mmMP1_SMN_IH_CREDIT                                                                            0x02c1
+#define mmMP1_SMN_IH_CREDIT_BASE_IDX                                                                   0
+#define mmMP1_SMN_IH_SW_INT                                                                            0x02c2
+#define mmMP1_SMN_IH_SW_INT_BASE_IDX                                                                   0
+#define mmMP1_SMN_IH_SW_INT_CTRL                                                                       0x02c3
+#define mmMP1_SMN_IH_SW_INT_CTRL_BASE_IDX                                                              0
+#define mmMP1_SMN_FPS_CNT                                                                              0x02c4
+#define mmMP1_SMN_FPS_CNT_BASE_IDX                                                                     0
+#define mmMP1_SMN_EXT_SCRATCH0                                                                         0x03c0
+#define mmMP1_SMN_EXT_SCRATCH0_BASE_IDX                                                                0
+#define mmMP1_SMN_EXT_SCRATCH1                                                                         0x03c1
+#define mmMP1_SMN_EXT_SCRATCH1_BASE_IDX                                                                0
+#define mmMP1_SMN_EXT_SCRATCH2                                                                         0x03c2
+#define mmMP1_SMN_EXT_SCRATCH2_BASE_IDX                                                                0
+#define mmMP1_SMN_EXT_SCRATCH3                                                                         0x03c3
+#define mmMP1_SMN_EXT_SCRATCH3_BASE_IDX                                                                0
+#define mmMP1_SMN_EXT_SCRATCH4                                                                         0x03c4
+#define mmMP1_SMN_EXT_SCRATCH4_BASE_IDX                                                                0
+#define mmMP1_SMN_EXT_SCRATCH5                                                                         0x03c5
+#define mmMP1_SMN_EXT_SCRATCH5_BASE_IDX                                                                0
+#define mmMP1_SMN_EXT_SCRATCH6                                                                         0x03c6
+#define mmMP1_SMN_EXT_SCRATCH6_BASE_IDX                                                                0
+#define mmMP1_SMN_EXT_SCRATCH7                                                                         0x03c7
+#define mmMP1_SMN_EXT_SCRATCH7_BASE_IDX                                                                0
+
+
+#endif
index 4c5097fa0c0986f3fe196d9f871dec0f9bf9a541..20329da53b0adf6e3d8b516b952ef1257a860e66 100644 (file)
-#ifndef _umc_8_7_0_SH_MASK_HEADER\r
-#define _umc_8_7_0_SH_MASK_HEADER\r
-\r
-//UMCCH0_0_GeccErrCntSel\r
-#define UMCCH0_0_GeccErrCntSel__GeccErrCntCsSel__SHIFT                                                        0x0\r
-#define UMCCH0_0_GeccErrCntSel__GeccErrInt__SHIFT                                                             0xc\r
-#define UMCCH0_0_GeccErrCntSel__GeccErrCntEn__SHIFT                                                           0xf\r
-#define UMCCH0_0_GeccErrCntSel__PoisonCntEn__SHIFT                                                            0x10\r
-#define UMCCH0_0_GeccErrCntSel__GeccErrCntCsSel_MASK                                                          0x0000000FL\r
-#define UMCCH0_0_GeccErrCntSel__GeccErrInt_MASK                                                               0x00003000L\r
-#define UMCCH0_0_GeccErrCntSel__GeccErrCntEn_MASK                                                             0x00008000L\r
-#define UMCCH0_0_GeccErrCntSel__PoisonCntEn_MASK                                                              0x00030000L\r
-//UMCCH0_0_GeccErrCnt\r
-#define UMCCH0_0_GeccErrCnt__GeccErrCnt__SHIFT                                                                0x0\r
-#define UMCCH0_0_GeccErrCnt__GeccUnCorrErrCnt__SHIFT                                                          0x10\r
-#define UMCCH0_0_GeccErrCnt__GeccErrCnt_MASK                                                                  0x0000FFFFL\r
-#define UMCCH0_0_GeccErrCnt__GeccUnCorrErrCnt_MASK                                                            0xFFFF0000L\r
-//MCA_UMC_UMC0_MCUMC_STATUST0\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCode__SHIFT                                                         0x0\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCodeExt__SHIFT                                                      0x10\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV22__SHIFT                                                          0x16\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrLsb__SHIFT                                                           0x18\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV30__SHIFT                                                          0x1e\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreId__SHIFT                                                         0x20\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV38__SHIFT                                                          0x26\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Scrub__SHIFT                                                             0x28\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV41__SHIFT                                                          0x29\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Poison__SHIFT                                                            0x2b\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Deferred__SHIFT                                                          0x2c\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__UECC__SHIFT                                                              0x2d\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__CECC__SHIFT                                                              0x2e\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV47__SHIFT                                                          0x2f\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Transparent__SHIFT                                                       0x34\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__SyndV__SHIFT                                                             0x35\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV54__SHIFT                                                          0x36\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__TCC__SHIFT                                                               0x37\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreIdVal__SHIFT                                                      0x38\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__PCC__SHIFT                                                               0x39\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrV__SHIFT                                                             0x3a\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__MiscV__SHIFT                                                             0x3b\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__En__SHIFT                                                                0x3c\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__UC__SHIFT                                                                0x3d\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Overflow__SHIFT                                                          0x3e\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Val__SHIFT                                                               0x3f\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCode_MASK                                                           0x000000000000FFFFL\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCodeExt_MASK                                                        0x00000000003F0000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV22_MASK                                                            0x0000000000C00000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrLsb_MASK                                                             0x000000003F000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV30_MASK                                                            0x00000000C0000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreId_MASK                                                           0x0000003F00000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV38_MASK                                                            0x000000C000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Scrub_MASK                                                               0x0000010000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV41_MASK                                                            0x0000060000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Poison_MASK                                                              0x0000080000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Deferred_MASK                                                            0x0000100000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__UECC_MASK                                                                0x0000200000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__CECC_MASK                                                                0x0000400000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV47_MASK                                                            0x000F800000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Transparent_MASK                                                         0x0010000000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__SyndV_MASK                                                               0x0020000000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV54_MASK                                                            0x0040000000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__TCC_MASK                                                                 0x0080000000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreIdVal_MASK                                                        0x0100000000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__PCC_MASK                                                                 0x0200000000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrV_MASK                                                               0x0400000000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__MiscV_MASK                                                               0x0800000000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__En_MASK                                                                  0x1000000000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__UC_MASK                                                                  0x2000000000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Overflow_MASK                                                            0x4000000000000000L\r
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Val_MASK                                                                 0x8000000000000000L\r
-//MCA_UMC_UMC0_MCUMC_ADDRT0\r
-#define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr__SHIFT                                                           0x0\r
-#define MCA_UMC_UMC0_MCUMC_ADDRT0__LSB__SHIFT                                                                 0x38\r
-#define MCA_UMC_UMC0_MCUMC_ADDRT0__Reserved__SHIFT                                                            0x3e\r
-#define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr_MASK                                                             0x00FFFFFFFFFFFFFFL\r
-#define MCA_UMC_UMC0_MCUMC_ADDRT0__LSB_MASK                                                                   0x3F00000000000000L\r
-#define MCA_UMC_UMC0_MCUMC_ADDRT0__Reserved_MASK                                                              0xC000000000000000L\r
-\r
-#endif\r
+/*
+ * Copyright (C) 2020  Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _umc_8_7_0_SH_MASK_HEADER
+#define _umc_8_7_0_SH_MASK_HEADER
+
+//UMCCH0_0_GeccErrCntSel
+#define UMCCH0_0_GeccErrCntSel__GeccErrCntCsSel__SHIFT                                                        0x0
+#define UMCCH0_0_GeccErrCntSel__GeccErrInt__SHIFT                                                             0xc
+#define UMCCH0_0_GeccErrCntSel__GeccErrCntEn__SHIFT                                                           0xf
+#define UMCCH0_0_GeccErrCntSel__PoisonCntEn__SHIFT                                                            0x10
+#define UMCCH0_0_GeccErrCntSel__GeccErrCntCsSel_MASK                                                          0x0000000FL
+#define UMCCH0_0_GeccErrCntSel__GeccErrInt_MASK                                                               0x00003000L
+#define UMCCH0_0_GeccErrCntSel__GeccErrCntEn_MASK                                                             0x00008000L
+#define UMCCH0_0_GeccErrCntSel__PoisonCntEn_MASK                                                              0x00030000L
+//UMCCH0_0_GeccErrCnt
+#define UMCCH0_0_GeccErrCnt__GeccErrCnt__SHIFT                                                                0x0
+#define UMCCH0_0_GeccErrCnt__GeccUnCorrErrCnt__SHIFT                                                          0x10
+#define UMCCH0_0_GeccErrCnt__GeccErrCnt_MASK                                                                  0x0000FFFFL
+#define UMCCH0_0_GeccErrCnt__GeccUnCorrErrCnt_MASK                                                            0xFFFF0000L
+//MCA_UMC_UMC0_MCUMC_STATUST0
+#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCode__SHIFT                                                         0x0
+#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCodeExt__SHIFT                                                      0x10
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV22__SHIFT                                                          0x16
+#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrLsb__SHIFT                                                           0x18
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV30__SHIFT                                                          0x1e
+#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreId__SHIFT                                                         0x20
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV38__SHIFT                                                          0x26
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Scrub__SHIFT                                                             0x28
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV41__SHIFT                                                          0x29
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Poison__SHIFT                                                            0x2b
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Deferred__SHIFT                                                          0x2c
+#define MCA_UMC_UMC0_MCUMC_STATUST0__UECC__SHIFT                                                              0x2d
+#define MCA_UMC_UMC0_MCUMC_STATUST0__CECC__SHIFT                                                              0x2e
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV47__SHIFT                                                          0x2f
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Transparent__SHIFT                                                       0x34
+#define MCA_UMC_UMC0_MCUMC_STATUST0__SyndV__SHIFT                                                             0x35
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV54__SHIFT                                                          0x36
+#define MCA_UMC_UMC0_MCUMC_STATUST0__TCC__SHIFT                                                               0x37
+#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreIdVal__SHIFT                                                      0x38
+#define MCA_UMC_UMC0_MCUMC_STATUST0__PCC__SHIFT                                                               0x39
+#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrV__SHIFT                                                             0x3a
+#define MCA_UMC_UMC0_MCUMC_STATUST0__MiscV__SHIFT                                                             0x3b
+#define MCA_UMC_UMC0_MCUMC_STATUST0__En__SHIFT                                                                0x3c
+#define MCA_UMC_UMC0_MCUMC_STATUST0__UC__SHIFT                                                                0x3d
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Overflow__SHIFT                                                          0x3e
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Val__SHIFT                                                               0x3f
+#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCode_MASK                                                           0x000000000000FFFFL
+#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCodeExt_MASK                                                        0x00000000003F0000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV22_MASK                                                            0x0000000000C00000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrLsb_MASK                                                             0x000000003F000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV30_MASK                                                            0x00000000C0000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreId_MASK                                                           0x0000003F00000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV38_MASK                                                            0x000000C000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Scrub_MASK                                                               0x0000010000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV41_MASK                                                            0x0000060000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Poison_MASK                                                              0x0000080000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Deferred_MASK                                                            0x0000100000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__UECC_MASK                                                                0x0000200000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__CECC_MASK                                                                0x0000400000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV47_MASK                                                            0x000F800000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Transparent_MASK                                                         0x0010000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__SyndV_MASK                                                               0x0020000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV54_MASK                                                            0x0040000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__TCC_MASK                                                                 0x0080000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreIdVal_MASK                                                        0x0100000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__PCC_MASK                                                                 0x0200000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrV_MASK                                                               0x0400000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__MiscV_MASK                                                               0x0800000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__En_MASK                                                                  0x1000000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__UC_MASK                                                                  0x2000000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Overflow_MASK                                                            0x4000000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Val_MASK                                                                 0x8000000000000000L
+//MCA_UMC_UMC0_MCUMC_ADDRT0
+#define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr__SHIFT                                                           0x0
+#define MCA_UMC_UMC0_MCUMC_ADDRT0__LSB__SHIFT                                                                 0x38
+#define MCA_UMC_UMC0_MCUMC_ADDRT0__Reserved__SHIFT                                                            0x3e
+#define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr_MASK                                                             0x00FFFFFFFFFFFFFFL
+#define MCA_UMC_UMC0_MCUMC_ADDRT0__LSB_MASK                                                                   0x3F00000000000000L
+#define MCA_UMC_UMC0_MCUMC_ADDRT0__Reserved_MASK                                                              0xC000000000000000L
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/cyan_skillfish_ip_offset.h b/drivers/gpu/drm/amd/include/cyan_skillfish_ip_offset.h
new file mode 100644 (file)
index 0000000..9cb5f36
--- /dev/null
@@ -0,0 +1,714 @@
+/*
+ * Copyright (C) 2018  Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef _cyan_skillfish_ip_offset_HEADER
+#define _cyan_skillfish_ip_offset_HEADER
+
+#define MAX_INSTANCE                                       6
+#define MAX_SEGMENT                                        5
+
+
+struct IP_BASE_INSTANCE 
+{
+    unsigned int segment[MAX_SEGMENT];
+};
+struct IP_BASE 
+{
+    struct IP_BASE_INSTANCE instance[MAX_INSTANCE];
+};
+
+
+static const struct IP_BASE ATHUB_BASE            ={ { { { 0x00000C00, 0, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE CLK_BASE            ={ { { { 0x00016C00, 0, 0, 0, 0 } },
+                                        { { 0x00016E00, 0, 0, 0, 0 } },
+                                        { { 0x00017000, 0, 0, 0, 0 } },
+                                        { { 0x00017200, 0, 0, 0, 0 } },
+                                        { { 0x00017E00, 0, 0, 0, 0 } },
+                                        { { 0x0001B000, 0, 0, 0, 0 } } } };
+static const struct IP_BASE DF_BASE            ={ { { { 0x00007000, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE DMU_BASE            ={ { { { 0x00000012, 0x000000C0, 0x000034C0, 0x00009000, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE FUSE_BASE            ={ { { { 0x00017400, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE GC_BASE            ={ { { { 0x00001260, 0x0000A000, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE HDP_BASE            ={ { { { 0x00000F20, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE MMHUB_BASE            ={ { { { 0x0001A000, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE MP0_BASE            ={ { { { 0x00016000, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE MP1_BASE            ={ { { { 0x00016000, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE NBIO_BASE            ={ { { { 0x00000000, 0x00000014, 0x00000D20, 0x00010400, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE OSSSYS_BASE            ={ { { { 0x000010A0, 0, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE SMUIO_BASE            ={ { { { 0x00016800, 0x00016A00, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE THM_BASE            ={ { { { 0x00016600, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE UMC0_BASE            ={ { { { 0x00014000, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE UVD0_BASE            ={ { { { 0x00007800, 0x00007E00, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } },
+                                       { { 0, 0, 0, 0, 0 } } } };
+
+
+#define ATHUB_BASE__INST0_SEG0                     0x00000C00
+#define ATHUB_BASE__INST0_SEG1                     0
+#define ATHUB_BASE__INST0_SEG2                     0
+#define ATHUB_BASE__INST0_SEG3                     0
+#define ATHUB_BASE__INST0_SEG4                     0
+
+#define ATHUB_BASE__INST1_SEG0                     0
+#define ATHUB_BASE__INST1_SEG1                     0
+#define ATHUB_BASE__INST1_SEG2                     0
+#define ATHUB_BASE__INST1_SEG3                     0
+#define ATHUB_BASE__INST1_SEG4                     0
+
+#define ATHUB_BASE__INST2_SEG0                     0
+#define ATHUB_BASE__INST2_SEG1                     0
+#define ATHUB_BASE__INST2_SEG2                     0
+#define ATHUB_BASE__INST2_SEG3                     0
+#define ATHUB_BASE__INST2_SEG4                     0
+
+#define ATHUB_BASE__INST3_SEG0                     0
+#define ATHUB_BASE__INST3_SEG1                     0
+#define ATHUB_BASE__INST3_SEG2                     0
+#define ATHUB_BASE__INST3_SEG3                     0
+#define ATHUB_BASE__INST3_SEG4                     0
+
+#define ATHUB_BASE__INST4_SEG0                     0
+#define ATHUB_BASE__INST4_SEG1                     0
+#define ATHUB_BASE__INST4_SEG2                     0
+#define ATHUB_BASE__INST4_SEG3                     0
+#define ATHUB_BASE__INST4_SEG4                     0
+
+#define ATHUB_BASE__INST5_SEG0                     0
+#define ATHUB_BASE__INST5_SEG1                     0
+#define ATHUB_BASE__INST5_SEG2                     0
+#define ATHUB_BASE__INST5_SEG3                     0
+#define ATHUB_BASE__INST5_SEG4                     0
+
+#define CLK_BASE__INST0_SEG0                       0x00016C00
+#define CLK_BASE__INST0_SEG1                       0
+#define CLK_BASE__INST0_SEG2                       0
+#define CLK_BASE__INST0_SEG3                       0
+#define CLK_BASE__INST0_SEG4                       0
+
+#define CLK_BASE__INST1_SEG0                       0x00016E00
+#define CLK_BASE__INST1_SEG1                       0
+#define CLK_BASE__INST1_SEG2                       0
+#define CLK_BASE__INST1_SEG3                       0
+#define CLK_BASE__INST1_SEG4                       0
+
+#define CLK_BASE__INST2_SEG0                       0x00017000
+#define CLK_BASE__INST2_SEG1                       0
+#define CLK_BASE__INST2_SEG2                       0
+#define CLK_BASE__INST2_SEG3                       0
+#define CLK_BASE__INST2_SEG4                       0
+
+#define CLK_BASE__INST3_SEG0                       0x00017200
+#define CLK_BASE__INST3_SEG1                       0
+#define CLK_BASE__INST3_SEG2                       0
+#define CLK_BASE__INST3_SEG3                       0
+#define CLK_BASE__INST3_SEG4                       0
+
+#define CLK_BASE__INST4_SEG0                       0x00017E00
+#define CLK_BASE__INST4_SEG1                       0
+#define CLK_BASE__INST4_SEG2                       0
+#define CLK_BASE__INST4_SEG3                       0
+#define CLK_BASE__INST4_SEG4                       0
+
+#define CLK_BASE__INST5_SEG0                       0x0001B000
+#define CLK_BASE__INST5_SEG1                       0
+#define CLK_BASE__INST5_SEG2                       0
+#define CLK_BASE__INST5_SEG3                       0
+#define CLK_BASE__INST5_SEG4                       0
+
+#define DF_BASE__INST0_SEG0                        0x00007000
+#define DF_BASE__INST0_SEG1                        0
+#define DF_BASE__INST0_SEG2                        0
+#define DF_BASE__INST0_SEG3                        0
+#define DF_BASE__INST0_SEG4                        0
+
+#define DF_BASE__INST1_SEG0                        0
+#define DF_BASE__INST1_SEG1                        0
+#define DF_BASE__INST1_SEG2                        0
+#define DF_BASE__INST1_SEG3                        0
+#define DF_BASE__INST1_SEG4                        0
+
+#define DF_BASE__INST2_SEG0                        0
+#define DF_BASE__INST2_SEG1                        0
+#define DF_BASE__INST2_SEG2                        0
+#define DF_BASE__INST2_SEG3                        0
+#define DF_BASE__INST2_SEG4                        0
+
+#define DF_BASE__INST3_SEG0                        0
+#define DF_BASE__INST3_SEG1                        0
+#define DF_BASE__INST3_SEG2                        0
+#define DF_BASE__INST3_SEG3                        0
+#define DF_BASE__INST3_SEG4                        0
+
+#define DF_BASE__INST4_SEG0                        0
+#define DF_BASE__INST4_SEG1                        0
+#define DF_BASE__INST4_SEG2                        0
+#define DF_BASE__INST4_SEG3                        0
+#define DF_BASE__INST4_SEG4                        0
+
+#define DF_BASE__INST5_SEG0                        0
+#define DF_BASE__INST5_SEG1                        0
+#define DF_BASE__INST5_SEG2                        0
+#define DF_BASE__INST5_SEG3                        0
+#define DF_BASE__INST5_SEG4                        0
+
+#define DMU_BASE__INST0_SEG0                       0x00000012
+#define DMU_BASE__INST0_SEG1                       0x000000C0
+#define DMU_BASE__INST0_SEG2                       0x000034C0
+#define DMU_BASE__INST0_SEG3                       0x00009000
+#define DMU_BASE__INST0_SEG4                       0
+
+#define DMU_BASE__INST1_SEG0                       0
+#define DMU_BASE__INST1_SEG1                       0
+#define DMU_BASE__INST1_SEG2                       0
+#define DMU_BASE__INST1_SEG3                       0
+#define DMU_BASE__INST1_SEG4                       0
+
+#define DMU_BASE__INST2_SEG0                       0
+#define DMU_BASE__INST2_SEG1                       0
+#define DMU_BASE__INST2_SEG2                       0
+#define DMU_BASE__INST2_SEG3                       0
+#define DMU_BASE__INST2_SEG4                       0
+
+#define DMU_BASE__INST3_SEG0                       0
+#define DMU_BASE__INST3_SEG1                       0
+#define DMU_BASE__INST3_SEG2                       0
+#define DMU_BASE__INST3_SEG3                       0
+#define DMU_BASE__INST3_SEG4                       0
+
+#define DMU_BASE__INST4_SEG0                       0
+#define DMU_BASE__INST4_SEG1                       0
+#define DMU_BASE__INST4_SEG2                       0
+#define DMU_BASE__INST4_SEG3                       0
+#define DMU_BASE__INST4_SEG4                       0
+
+#define DMU_BASE__INST5_SEG0                       0
+#define DMU_BASE__INST5_SEG1                       0
+#define DMU_BASE__INST5_SEG2                       0
+#define DMU_BASE__INST5_SEG3                       0
+#define DMU_BASE__INST5_SEG4                       0
+
+#define FUSE_BASE__INST0_SEG0                      0x00017400
+#define FUSE_BASE__INST0_SEG1                      0
+#define FUSE_BASE__INST0_SEG2                      0
+#define FUSE_BASE__INST0_SEG3                      0
+#define FUSE_BASE__INST0_SEG4                      0
+
+#define FUSE_BASE__INST1_SEG0                      0
+#define FUSE_BASE__INST1_SEG1                      0
+#define FUSE_BASE__INST1_SEG2                      0
+#define FUSE_BASE__INST1_SEG3                      0
+#define FUSE_BASE__INST1_SEG4                      0
+
+#define FUSE_BASE__INST2_SEG0                      0
+#define FUSE_BASE__INST2_SEG1                      0
+#define FUSE_BASE__INST2_SEG2                      0
+#define FUSE_BASE__INST2_SEG3                      0
+#define FUSE_BASE__INST2_SEG4                      0
+
+#define FUSE_BASE__INST3_SEG0                      0
+#define FUSE_BASE__INST3_SEG1                      0
+#define FUSE_BASE__INST3_SEG2                      0
+#define FUSE_BASE__INST3_SEG3                      0
+#define FUSE_BASE__INST3_SEG4                      0
+
+#define FUSE_BASE__INST4_SEG0                      0
+#define FUSE_BASE__INST4_SEG1                      0
+#define FUSE_BASE__INST4_SEG2                      0
+#define FUSE_BASE__INST4_SEG3                      0
+#define FUSE_BASE__INST4_SEG4                      0
+
+#define FUSE_BASE__INST5_SEG0                      0
+#define FUSE_BASE__INST5_SEG1                      0
+#define FUSE_BASE__INST5_SEG2                      0
+#define FUSE_BASE__INST5_SEG3                      0
+#define FUSE_BASE__INST5_SEG4                      0
+
+#define GC_BASE__INST0_SEG0                        0x00001260
+#define GC_BASE__INST0_SEG1                        0x0000A000
+#define GC_BASE__INST0_SEG2                        0
+#define GC_BASE__INST0_SEG3                        0
+#define GC_BASE__INST0_SEG4                        0
+
+#define GC_BASE__INST1_SEG0                        0
+#define GC_BASE__INST1_SEG1                        0
+#define GC_BASE__INST1_SEG2                        0
+#define GC_BASE__INST1_SEG3                        0
+#define GC_BASE__INST1_SEG4                        0
+
+#define GC_BASE__INST2_SEG0                        0
+#define GC_BASE__INST2_SEG1                        0
+#define GC_BASE__INST2_SEG2                        0
+#define GC_BASE__INST2_SEG3                        0
+#define GC_BASE__INST2_SEG4                        0
+
+#define GC_BASE__INST3_SEG0                        0
+#define GC_BASE__INST3_SEG1                        0
+#define GC_BASE__INST3_SEG2                        0
+#define GC_BASE__INST3_SEG3                        0
+#define GC_BASE__INST3_SEG4                        0
+
+#define GC_BASE__INST4_SEG0                        0
+#define GC_BASE__INST4_SEG1                        0
+#define GC_BASE__INST4_SEG2                        0
+#define GC_BASE__INST4_SEG3                        0
+#define GC_BASE__INST4_SEG4                        0
+
+#define GC_BASE__INST5_SEG0                        0
+#define GC_BASE__INST5_SEG1                        0
+#define GC_BASE__INST5_SEG2                        0
+#define GC_BASE__INST5_SEG3                        0
+#define GC_BASE__INST5_SEG4                        0
+
+#define HDP_BASE__INST0_SEG0                       0x00000F20
+#define HDP_BASE__INST0_SEG1                       0
+#define HDP_BASE__INST0_SEG2                       0
+#define HDP_BASE__INST0_SEG3                       0
+#define HDP_BASE__INST0_SEG4                       0
+
+#define HDP_BASE__INST1_SEG0                       0
+#define HDP_BASE__INST1_SEG1                       0
+#define HDP_BASE__INST1_SEG2                       0
+#define HDP_BASE__INST1_SEG3                       0
+#define HDP_BASE__INST1_SEG4                       0
+
+#define HDP_BASE__INST2_SEG0                       0
+#define HDP_BASE__INST2_SEG1                       0
+#define HDP_BASE__INST2_SEG2                       0
+#define HDP_BASE__INST2_SEG3                       0
+#define HDP_BASE__INST2_SEG4                       0
+
+#define HDP_BASE__INST3_SEG0                       0
+#define HDP_BASE__INST3_SEG1                       0
+#define HDP_BASE__INST3_SEG2                       0
+#define HDP_BASE__INST3_SEG3                       0
+#define HDP_BASE__INST3_SEG4                       0
+
+#define HDP_BASE__INST4_SEG0                       0
+#define HDP_BASE__INST4_SEG1                       0
+#define HDP_BASE__INST4_SEG2                       0
+#define HDP_BASE__INST4_SEG3                       0
+#define HDP_BASE__INST4_SEG4                       0
+
+#define HDP_BASE__INST5_SEG0                       0
+#define HDP_BASE__INST5_SEG1                       0
+#define HDP_BASE__INST5_SEG2                       0
+#define HDP_BASE__INST5_SEG3                       0
+#define HDP_BASE__INST5_SEG4                       0
+
+#define MMHUB_BASE__INST0_SEG0                     0x0001A000
+#define MMHUB_BASE__INST0_SEG1                     0
+#define MMHUB_BASE__INST0_SEG2                     0
+#define MMHUB_BASE__INST0_SEG3                     0
+#define MMHUB_BASE__INST0_SEG4                     0
+
+#define MMHUB_BASE__INST1_SEG0                     0
+#define MMHUB_BASE__INST1_SEG1                     0
+#define MMHUB_BASE__INST1_SEG2                     0
+#define MMHUB_BASE__INST1_SEG3                     0
+#define MMHUB_BASE__INST1_SEG4                     0
+
+#define MMHUB_BASE__INST2_SEG0                     0
+#define MMHUB_BASE__INST2_SEG1                     0
+#define MMHUB_BASE__INST2_SEG2                     0
+#define MMHUB_BASE__INST2_SEG3                     0
+#define MMHUB_BASE__INST2_SEG4                     0
+
+#define MMHUB_BASE__INST3_SEG0                     0
+#define MMHUB_BASE__INST3_SEG1                     0
+#define MMHUB_BASE__INST3_SEG2                     0
+#define MMHUB_BASE__INST3_SEG3                     0
+#define MMHUB_BASE__INST3_SEG4                     0
+
+#define MMHUB_BASE__INST4_SEG0                     0
+#define MMHUB_BASE__INST4_SEG1                     0
+#define MMHUB_BASE__INST4_SEG2                     0
+#define MMHUB_BASE__INST4_SEG3                     0
+#define MMHUB_BASE__INST4_SEG4                     0
+
+#define MMHUB_BASE__INST5_SEG0                     0
+#define MMHUB_BASE__INST5_SEG1                     0
+#define MMHUB_BASE__INST5_SEG2                     0
+#define MMHUB_BASE__INST5_SEG3                     0
+#define MMHUB_BASE__INST5_SEG4                     0
+
+#define MP0_BASE__INST0_SEG0                       0x00016000
+#define MP0_BASE__INST0_SEG1                       0
+#define MP0_BASE__INST0_SEG2                       0
+#define MP0_BASE__INST0_SEG3                       0
+#define MP0_BASE__INST0_SEG4                       0
+
+#define MP0_BASE__INST1_SEG0                       0
+#define MP0_BASE__INST1_SEG1                       0
+#define MP0_BASE__INST1_SEG2                       0
+#define MP0_BASE__INST1_SEG3                       0
+#define MP0_BASE__INST1_SEG4                       0
+
+#define MP0_BASE__INST2_SEG0                       0
+#define MP0_BASE__INST2_SEG1                       0
+#define MP0_BASE__INST2_SEG2                       0
+#define MP0_BASE__INST2_SEG3                       0
+#define MP0_BASE__INST2_SEG4                       0
+
+#define MP0_BASE__INST3_SEG0                       0
+#define MP0_BASE__INST3_SEG1                       0
+#define MP0_BASE__INST3_SEG2                       0
+#define MP0_BASE__INST3_SEG3                       0
+#define MP0_BASE__INST3_SEG4                       0
+
+#define MP0_BASE__INST4_SEG0                       0
+#define MP0_BASE__INST4_SEG1                       0
+#define MP0_BASE__INST4_SEG2                       0
+#define MP0_BASE__INST4_SEG3                       0
+#define MP0_BASE__INST4_SEG4                       0
+
+#define MP0_BASE__INST5_SEG0                       0
+#define MP0_BASE__INST5_SEG1                       0
+#define MP0_BASE__INST5_SEG2                       0
+#define MP0_BASE__INST5_SEG3                       0
+#define MP0_BASE__INST5_SEG4                       0
+
+#define MP1_BASE__INST0_SEG0                       0x00016000
+#define MP1_BASE__INST0_SEG1                       0
+#define MP1_BASE__INST0_SEG2                       0
+#define MP1_BASE__INST0_SEG3                       0
+#define MP1_BASE__INST0_SEG4                       0
+
+#define MP1_BASE__INST1_SEG0                       0
+#define MP1_BASE__INST1_SEG1                       0
+#define MP1_BASE__INST1_SEG2                       0
+#define MP1_BASE__INST1_SEG3                       0
+#define MP1_BASE__INST1_SEG4                       0
+
+#define MP1_BASE__INST2_SEG0                       0
+#define MP1_BASE__INST2_SEG1                       0
+#define MP1_BASE__INST2_SEG2                       0
+#define MP1_BASE__INST2_SEG3                       0
+#define MP1_BASE__INST2_SEG4                       0
+
+#define MP1_BASE__INST3_SEG0                       0
+#define MP1_BASE__INST3_SEG1                       0
+#define MP1_BASE__INST3_SEG2                       0
+#define MP1_BASE__INST3_SEG3                       0
+#define MP1_BASE__INST3_SEG4                       0
+
+#define MP1_BASE__INST4_SEG0                       0
+#define MP1_BASE__INST4_SEG1                       0
+#define MP1_BASE__INST4_SEG2                       0
+#define MP1_BASE__INST4_SEG3                       0
+#define MP1_BASE__INST4_SEG4                       0
+
+#define MP1_BASE__INST5_SEG0                       0
+#define MP1_BASE__INST5_SEG1                       0
+#define MP1_BASE__INST5_SEG2                       0
+#define MP1_BASE__INST5_SEG3                       0
+#define MP1_BASE__INST5_SEG4                       0
+
+#define NBIO_BASE__INST0_SEG0                     0x00000000
+#define NBIO_BASE__INST0_SEG1                     0x00000014
+#define NBIO_BASE__INST0_SEG2                     0x00000D20
+#define NBIO_BASE__INST0_SEG3                     0x00010400
+#define NBIO_BASE__INST0_SEG4                     0
+
+#define NBIO_BASE__INST1_SEG0                     0
+#define NBIO_BASE__INST1_SEG1                     0
+#define NBIO_BASE__INST1_SEG2                     0
+#define NBIO_BASE__INST1_SEG3                     0
+#define NBIO_BASE__INST1_SEG4                     0
+
+#define NBIO_BASE__INST2_SEG0                     0
+#define NBIO_BASE__INST2_SEG1                     0
+#define NBIO_BASE__INST2_SEG2                     0
+#define NBIO_BASE__INST2_SEG3                     0
+#define NBIO_BASE__INST2_SEG4                     0
+
+#define NBIO_BASE__INST3_SEG0                     0
+#define NBIO_BASE__INST3_SEG1                     0
+#define NBIO_BASE__INST3_SEG2                     0
+#define NBIO_BASE__INST3_SEG3                     0
+#define NBIO_BASE__INST3_SEG4                     0
+
+#define NBIO_BASE__INST4_SEG0                     0
+#define NBIO_BASE__INST4_SEG1                     0
+#define NBIO_BASE__INST4_SEG2                     0
+#define NBIO_BASE__INST4_SEG3                     0
+#define NBIO_BASE__INST4_SEG4                     0
+
+#define NBIO_BASE__INST5_SEG0                     0
+#define NBIO_BASE__INST5_SEG1                     0
+#define NBIO_BASE__INST5_SEG2                     0
+#define NBIO_BASE__INST5_SEG3                     0
+#define NBIO_BASE__INST5_SEG4                     0
+
+#define OSSSYS_BASE__INST0_SEG0                    0x000010A0
+#define OSSSYS_BASE__INST0_SEG1                    0
+#define OSSSYS_BASE__INST0_SEG2                    0
+#define OSSSYS_BASE__INST0_SEG3                    0
+#define OSSSYS_BASE__INST0_SEG4                    0
+
+#define OSSSYS_BASE__INST1_SEG0                    0
+#define OSSSYS_BASE__INST1_SEG1                    0
+#define OSSSYS_BASE__INST1_SEG2                    0
+#define OSSSYS_BASE__INST1_SEG3                    0
+#define OSSSYS_BASE__INST1_SEG4                    0
+
+#define OSSSYS_BASE__INST2_SEG0                    0
+#define OSSSYS_BASE__INST2_SEG1                    0
+#define OSSSYS_BASE__INST2_SEG2                    0
+#define OSSSYS_BASE__INST2_SEG3                    0
+#define OSSSYS_BASE__INST2_SEG4                    0
+
+#define OSSSYS_BASE__INST3_SEG0                    0
+#define OSSSYS_BASE__INST3_SEG1                    0
+#define OSSSYS_BASE__INST3_SEG2                    0
+#define OSSSYS_BASE__INST3_SEG3                    0
+#define OSSSYS_BASE__INST3_SEG4                    0
+
+#define OSSSYS_BASE__INST4_SEG0                    0
+#define OSSSYS_BASE__INST4_SEG1                    0
+#define OSSSYS_BASE__INST4_SEG2                    0
+#define OSSSYS_BASE__INST4_SEG3                    0
+#define OSSSYS_BASE__INST4_SEG4                    0
+
+#define OSSSYS_BASE__INST5_SEG0                    0
+#define OSSSYS_BASE__INST5_SEG1                    0
+#define OSSSYS_BASE__INST5_SEG2                    0
+#define OSSSYS_BASE__INST5_SEG3                    0
+#define OSSSYS_BASE__INST5_SEG4                    0
+
+#define SMUIO_BASE__INST0_SEG0                     0x00016800
+#define SMUIO_BASE__INST0_SEG1                     0x00016A00
+#define SMUIO_BASE__INST0_SEG2                     0
+#define SMUIO_BASE__INST0_SEG3                     0
+#define SMUIO_BASE__INST0_SEG4                     0
+
+#define SMUIO_BASE__INST1_SEG0                     0
+#define SMUIO_BASE__INST1_SEG1                     0
+#define SMUIO_BASE__INST1_SEG2                     0
+#define SMUIO_BASE__INST1_SEG3                     0
+#define SMUIO_BASE__INST1_SEG4                     0
+
+#define SMUIO_BASE__INST2_SEG0                     0
+#define SMUIO_BASE__INST2_SEG1                     0
+#define SMUIO_BASE__INST2_SEG2                     0
+#define SMUIO_BASE__INST2_SEG3                     0
+#define SMUIO_BASE__INST2_SEG4                     0
+
+#define SMUIO_BASE__INST3_SEG0                     0
+#define SMUIO_BASE__INST3_SEG1                     0
+#define SMUIO_BASE__INST3_SEG2                     0
+#define SMUIO_BASE__INST3_SEG3                     0
+#define SMUIO_BASE__INST3_SEG4                     0
+
+#define SMUIO_BASE__INST4_SEG0                     0
+#define SMUIO_BASE__INST4_SEG1                     0
+#define SMUIO_BASE__INST4_SEG2                     0
+#define SMUIO_BASE__INST4_SEG3                     0
+#define SMUIO_BASE__INST4_SEG4                     0
+
+#define SMUIO_BASE__INST5_SEG0                     0
+#define SMUIO_BASE__INST5_SEG1                     0
+#define SMUIO_BASE__INST5_SEG2                     0
+#define SMUIO_BASE__INST5_SEG3                     0
+#define SMUIO_BASE__INST5_SEG4                     0
+
+#define THM_BASE__INST0_SEG0                       0x00016600
+#define THM_BASE__INST0_SEG1                       0
+#define THM_BASE__INST0_SEG2                       0
+#define THM_BASE__INST0_SEG3                       0
+#define THM_BASE__INST0_SEG4                       0
+
+#define THM_BASE__INST1_SEG0                       0
+#define THM_BASE__INST1_SEG1                       0
+#define THM_BASE__INST1_SEG2                       0
+#define THM_BASE__INST1_SEG3                       0
+#define THM_BASE__INST1_SEG4                       0
+
+#define THM_BASE__INST2_SEG0                       0
+#define THM_BASE__INST2_SEG1                       0
+#define THM_BASE__INST2_SEG2                       0
+#define THM_BASE__INST2_SEG3                       0
+#define THM_BASE__INST2_SEG4                       0
+
+#define THM_BASE__INST3_SEG0                       0
+#define THM_BASE__INST3_SEG1                       0
+#define THM_BASE__INST3_SEG2                       0
+#define THM_BASE__INST3_SEG3                       0
+#define THM_BASE__INST3_SEG4                       0
+
+#define THM_BASE__INST4_SEG0                       0
+#define THM_BASE__INST4_SEG1                       0
+#define THM_BASE__INST4_SEG2                       0
+#define THM_BASE__INST4_SEG3                       0
+#define THM_BASE__INST4_SEG4                       0
+
+#define THM_BASE__INST5_SEG0                       0
+#define THM_BASE__INST5_SEG1                       0
+#define THM_BASE__INST5_SEG2                       0
+#define THM_BASE__INST5_SEG3                       0
+#define THM_BASE__INST5_SEG4                       0
+
+#define UMC0_BASE__INST0_SEG0                      0x00014000
+#define UMC0_BASE__INST0_SEG1                      0
+#define UMC0_BASE__INST0_SEG2                      0
+#define UMC0_BASE__INST0_SEG3                      0
+#define UMC0_BASE__INST0_SEG4                      0
+
+#define UMC0_BASE__INST1_SEG0                      0
+#define UMC0_BASE__INST1_SEG1                      0
+#define UMC0_BASE__INST1_SEG2                      0
+#define UMC0_BASE__INST1_SEG3                      0
+#define UMC0_BASE__INST1_SEG4                      0
+
+#define UMC0_BASE__INST2_SEG0                      0
+#define UMC0_BASE__INST2_SEG1                      0
+#define UMC0_BASE__INST2_SEG2                      0
+#define UMC0_BASE__INST2_SEG3                      0
+#define UMC0_BASE__INST2_SEG4                      0
+
+#define UMC0_BASE__INST3_SEG0                      0
+#define UMC0_BASE__INST3_SEG1                      0
+#define UMC0_BASE__INST3_SEG2                      0
+#define UMC0_BASE__INST3_SEG3                      0
+#define UMC0_BASE__INST3_SEG4                      0
+
+#define UMC0_BASE__INST4_SEG0                      0
+#define UMC0_BASE__INST4_SEG1                      0
+#define UMC0_BASE__INST4_SEG2                      0
+#define UMC0_BASE__INST4_SEG3                      0
+#define UMC0_BASE__INST4_SEG4                      0
+
+#define UMC0_BASE__INST5_SEG0                      0
+#define UMC0_BASE__INST5_SEG1                      0
+#define UMC0_BASE__INST5_SEG2                      0
+#define UMC0_BASE__INST5_SEG3                      0
+#define UMC0_BASE__INST5_SEG4                      0
+
+#define UVD0_BASE__INST0_SEG0                      0x00007800
+#define UVD0_BASE__INST0_SEG1                      0x00007E00
+#define UVD0_BASE__INST0_SEG2                      0
+#define UVD0_BASE__INST0_SEG3                      0
+#define UVD0_BASE__INST0_SEG4                      0
+
+#define UVD0_BASE__INST1_SEG0                      0
+#define UVD0_BASE__INST1_SEG1                      0
+#define UVD0_BASE__INST1_SEG2                      0
+#define UVD0_BASE__INST1_SEG3                      0
+#define UVD0_BASE__INST1_SEG4                      0
+
+#define UVD0_BASE__INST2_SEG0                      0
+#define UVD0_BASE__INST2_SEG1                      0
+#define UVD0_BASE__INST2_SEG2                      0
+#define UVD0_BASE__INST2_SEG3                      0
+#define UVD0_BASE__INST2_SEG4                      0
+
+#define UVD0_BASE__INST3_SEG0                      0
+#define UVD0_BASE__INST3_SEG1                      0
+#define UVD0_BASE__INST3_SEG2                      0
+#define UVD0_BASE__INST3_SEG3                      0
+#define UVD0_BASE__INST3_SEG4                      0
+
+#define UVD0_BASE__INST4_SEG0                      0
+#define UVD0_BASE__INST4_SEG1                      0
+#define UVD0_BASE__INST4_SEG2                      0
+#define UVD0_BASE__INST4_SEG3                      0
+#define UVD0_BASE__INST4_SEG4                      0
+
+#define UVD0_BASE__INST5_SEG0                      0
+#define UVD0_BASE__INST5_SEG1                      0
+#define UVD0_BASE__INST5_SEG2                      0
+#define UVD0_BASE__INST5_SEG3                      0
+#define UVD0_BASE__INST5_SEG4                      0
+
+#endif
+
index f6e0e7d8a00771ada7cc280a34ee737fa6d4ec00..d03e6fa2bf1adf269367843ea52a21cb4285cf05 100644 (file)
@@ -450,6 +450,7 @@ struct amdgpu_pm {
 
        /* Used for I2C access to various EEPROMs on relevant ASICs */
        struct i2c_adapter smu_i2c;
+       struct mutex            smu_i2c_mutex;
        struct list_head        pm_attr_list;
 };
 
index 3e89852e48202db212c09d44b7ecf33a5da2d9bf..c2c201b8e3cf1ae9ddf9bd0c619c3eaa280717c2 100644 (file)
@@ -231,6 +231,7 @@ struct smu_user_dpm_profile {
        uint32_t power_limit;
        uint32_t fan_speed_percent;
        uint32_t flags;
+       uint32_t user_od;
 
        /* user clock state information */
        uint32_t clk_mask[SMU_CLK_COUNT];
@@ -352,6 +353,7 @@ struct smu_table_context
 
        void                            *overdrive_table;
        void                            *boot_overdrive_table;
+       void                            *user_overdrive_table;
 
        uint32_t                        gpu_metrics_table_size;
        void                            *gpu_metrics_table;
@@ -623,6 +625,12 @@ struct pptable_funcs {
                                 enum PP_OD_DPM_TABLE_COMMAND type,
                                 long *input, uint32_t size);
 
+       /**
+        * @restore_user_od_settings: Restore the user customized
+        *                            OD settings on S3/S4/Runpm resume.
+        */
+       int (*restore_user_od_settings)(struct smu_context *smu);
+
        /**
         * @get_clock_by_type_with_latency: Get the speed and latency of a clock
         *                                  domain.
diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h
new file mode 100644 (file)
index 0000000..8a08ecc
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef __SMU11_DRIVER_IF_CYAN_SKILLFISH_H__
+#define __SMU11_DRIVER_IF_CYAN_SKILLFISH_H__
+
+// *** IMPORTANT ***
+// Always increment the interface version if
+// any structure is changed in this file
+#define MP1_DRIVER_IF_VERSION 0x8
+
+#define TABLE_BIOS_IF            0 // Called by BIOS
+#define TABLE_WATERMARKS         1 // Called by Driver; defined here, but not used, for backward compatible
+#define TABLE_PMSTATUSLOG        3 // Called by Tools for Agm logging
+#define TABLE_DPMCLOCKS          4 // Called by Driver; defined here, but not used, for backward compatible
+#define TABLE_MOMENTARY_PM       5 // Called by Tools; defined here, but not used, for backward compatible
+#define TABLE_COUNT              6
+
+#define NUM_DSPCLK_LEVELS              8
+#define NUM_SOCCLK_DPM_LEVELS  8
+#define NUM_DCEFCLK_DPM_LEVELS 4
+#define NUM_FCLK_DPM_LEVELS            4
+#define NUM_MEMCLK_DPM_LEVELS  4
+
+#define NUMBER_OF_PSTATES              8
+#define NUMBER_OF_CORES                        8
+
+typedef enum {
+       S3_TYPE_ENTRY,
+       S5_TYPE_ENTRY,
+} Sleep_Type_e;
+
+typedef enum {
+       GFX_OFF = 0,
+       GFX_ON  = 1,
+} GFX_Mode_e;
+
+typedef enum {
+       CPU_P0 = 0,
+       CPU_P1,
+       CPU_P2,
+       CPU_P3,
+       CPU_P4,
+       CPU_P5,
+       CPU_P6,
+       CPU_P7
+} CPU_PState_e;
+
+typedef enum {
+       CPU_CORE0 = 0,
+       CPU_CORE1,
+       CPU_CORE2,
+       CPU_CORE3,
+       CPU_CORE4,
+       CPU_CORE5,
+       CPU_CORE6,
+       CPU_CORE7
+} CORE_ID_e;
+
+typedef enum {
+       DF_DPM0 = 0,
+       DF_DPM1,
+       DF_DPM2,
+       DF_DPM3,
+       DF_PState_Count
+} DF_PState_e;
+
+typedef enum {
+       GFX_DPM0 = 0,
+       GFX_DPM1,
+       GFX_DPM2,
+       GFX_DPM3,
+       GFX_PState_Count
+} GFX_PState_e;
+
+#endif
index 61c87c39be80dbd6b2e92cb597a74ada7369a250..63b8701fd4668a307190c1fed51dcfba5359af14 100644 (file)
 #define FEATURE_GFX_EDC_BIT             49
 #define FEATURE_GFX_PER_PART_VMIN_BIT   50
 #define FEATURE_SMART_SHIFT_BIT         51
-#define FEATURE_SPARE_52_BIT            52
+#define FEATURE_APT_BIT                 52
 #define FEATURE_SPARE_53_BIT            53
 #define FEATURE_SPARE_54_BIT            54
 #define FEATURE_SPARE_55_BIT            55
@@ -211,6 +211,7 @@ typedef enum {
 #define THROTTLER_FIT_BIT          17
 #define THROTTLER_PPM_BIT          18
 #define THROTTLER_APCC_BIT         19
+#define THROTTLER_COUNT            20
 
 // FW DState Features Control Bits
 // FW DState Features Control Bits
@@ -1406,7 +1407,67 @@ typedef struct {
 } SmuMetrics_t;
 
 typedef struct {
-  SmuMetrics_t SmuMetrics;
+  uint32_t CurrClock[PPCLK_COUNT];
+
+  uint16_t AverageGfxclkFrequencyPreDs;
+  uint16_t AverageGfxclkFrequencyPostDs;
+  uint16_t AverageFclkFrequencyPreDs;
+  uint16_t AverageFclkFrequencyPostDs;
+  uint16_t AverageUclkFrequencyPreDs  ;
+  uint16_t AverageUclkFrequencyPostDs  ;
+
+
+  uint16_t AverageGfxActivity    ;
+  uint16_t AverageUclkActivity   ;
+  uint8_t  CurrSocVoltageOffset  ;
+  uint8_t  CurrGfxVoltageOffset  ;
+  uint8_t  CurrMemVidOffset      ;
+  uint8_t  Padding8        ;
+  uint16_t AverageSocketPower    ;
+  uint16_t TemperatureEdge       ;
+  uint16_t TemperatureHotspot    ;
+  uint16_t TemperatureMem        ;
+  uint16_t TemperatureVrGfx      ;
+  uint16_t TemperatureVrMem0     ;
+  uint16_t TemperatureVrMem1     ;
+  uint16_t TemperatureVrSoc      ;
+  uint16_t TemperatureLiquid0    ;
+  uint16_t TemperatureLiquid1    ;
+  uint16_t TemperaturePlx        ;
+  uint16_t Padding16             ;
+  uint32_t AccCnt                ;
+  uint8_t  ThrottlingPercentage[THROTTLER_COUNT];
+
+
+  uint8_t  LinkDpmLevel;
+  uint8_t  CurrFanPwm;
+  uint16_t CurrFanSpeed;
+
+  //BACO metrics, PMFW-1721
+  //metrics for D3hot entry/exit and driver ARM msgs
+  uint8_t D3HotEntryCountPerMode[D3HOT_SEQUENCE_COUNT];
+  uint8_t D3HotExitCountPerMode[D3HOT_SEQUENCE_COUNT];
+  uint8_t ArmMsgReceivedCountPerMode[D3HOT_SEQUENCE_COUNT];
+
+  //PMFW-4362
+  uint32_t EnergyAccumulator;
+  uint16_t AverageVclk0Frequency  ;
+  uint16_t AverageDclk0Frequency  ;
+  uint16_t AverageVclk1Frequency  ;
+  uint16_t AverageDclk1Frequency  ;
+  uint16_t VcnActivityPercentage  ; //place holder, David N. to provide full sequence
+  uint8_t  PcieRate               ;
+  uint8_t  PcieWidth              ;
+  uint16_t AverageGfxclkFrequencyTarget;
+  uint16_t Padding16_2;
+
+} SmuMetrics_V2_t;
+
+typedef struct {
+  union {
+    SmuMetrics_t SmuMetrics;
+    SmuMetrics_V2_t SmuMetrics_V2;
+  };
   uint32_t Spare[1];
 
   // Padding - ignore
index f61b5c914a3d92458edf40b8378582289938a5b9..403bc1bf8a770fb328c71fc8fcb502cbd2eded83 100644 (file)
 #define SMU11_DRIVER_IF_VERSION_NV10 0x37
 #define SMU11_DRIVER_IF_VERSION_NV12 0x38
 #define SMU11_DRIVER_IF_VERSION_NV14 0x38
-#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x3D
+#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x40
 #define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0xE
 #define SMU11_DRIVER_IF_VERSION_VANGOGH 0x03
 #define SMU11_DRIVER_IF_VERSION_Dimgrey_Cavefish 0xF
 #define SMU11_DRIVER_IF_VERSION_Beige_Goby 0xD
+#define SMU11_DRIVER_IF_VERSION_Cyan_Skillfish 0x8
 
 /* MP Apertures */
 #define MP0_Public                     0x03800000
@@ -302,5 +303,7 @@ void smu_v11_0_interrupt_work(struct smu_context *smu);
 
 int smu_v11_0_set_light_sbr(struct smu_context *smu, bool enable);
 
+int smu_v11_0_restore_user_od_settings(struct smu_context *smu);
+
 #endif
 #endif
diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_8_pmfw.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_8_pmfw.h
new file mode 100644 (file)
index 0000000..bd4fcb6
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __SMU_V11_8_0_PMFW_H__
+#define __SMU_V11_8_0_PMFW_H__
+
+#pragma pack(push, 1)
+
+#define ENABLE_DEBUG_FEATURES
+
+// Feature Control Defines
+#define FEATURE_CCLK_CONTROLLER_BIT       0
+#define FEATURE_GFXCLK_EFFT_FREQ_BIT      1
+#define FEATURE_DATA_CALCULATION_BIT      2
+#define FEATURE_THERMAL_BIT               3
+#define FEATURE_PLL_POWER_DOWN_BIT        4
+#define FEATURE_FCLK_DPM_BIT              5
+#define FEATURE_GFX_DPM_BIT               6
+#define FEATURE_DS_GFXCLK_BIT             7
+#define FEATURE_DS_SOCCLK_BIT             8
+#define FEATURE_DS_LCLK_BIT               9
+#define FEATURE_CORE_CSTATES_BIT          10
+#define FEATURE_G6_SSC_BIT                11 //G6 memory UCLK and UCLK_DIV SS
+#define FEATURE_RM_BIT                    12
+#define FEATURE_SOC_DPM_BIT               13
+#define FEATURE_DS_SMNCLK_BIT             14
+#define FEATURE_DS_MP1CLK_BIT             15
+#define FEATURE_DS_MP0CLK_BIT             16
+#define FEATURE_MGCG_BIT                  17
+#define FEATURE_DS_FUSE_SRAM_BIT          18
+#define FEATURE_GFX_CKS_BIT               19
+#define FEATURE_FP_THROTTLING_BIT         20
+#define FEATURE_PROCHOT_BIT               21
+#define FEATURE_CPUOFF_BIT                22
+#define FEATURE_UMC_THROTTLE_BIT          23
+#define FEATURE_DF_THROTTLE_BIT           24
+#define FEATURE_DS_MP3CLK_BIT             25
+#define FEATURE_DS_SHUBCLK_BIT            26
+#define FEATURE_TDC_BIT                   27 //Legacy APM_BIT
+#define FEATURE_UMC_CAL_SHARING_BIT       28
+#define FEATURE_DFLL_BTC_CALIBRATION_BIT  29
+#define FEATURE_EDC_BIT                   30
+#define FEATURE_DLDO_BIT                  31
+#define FEATURE_MEAS_DRAM_BLACKOUT_BIT    32
+#define FEATURE_CC1_BIT                   33
+#define FEATURE_PPT_BIT                   34
+#define FEATURE_STAPM_BIT                 35
+#define FEATURE_CSTATE_BOOST_BIT          36
+#define FEATURE_SPARE_37_BIT              37
+#define FEATURE_SPARE_38_BIT              38
+#define FEATURE_SPARE_39_BIT              39
+#define FEATURE_SPARE_40_BIT              40
+#define FEATURE_SPARE_41_BIT              41
+#define FEATURE_SPARE_42_BIT              42
+#define FEATURE_SPARE_43_BIT              43
+#define FEATURE_SPARE_44_BIT              44
+#define FEATURE_SPARE_45_BIT              45
+#define FEATURE_SPARE_46_BIT              46
+#define FEATURE_SPARE_47_BIT              47
+#define FEATURE_SPARE_48_BIT              48
+#define FEATURE_SPARE_49_BIT              49
+#define FEATURE_SPARE_50_BIT              50
+#define FEATURE_SPARE_51_BIT              51
+#define FEATURE_SPARE_52_BIT              52
+#define FEATURE_SPARE_53_BIT              53
+#define FEATURE_SPARE_54_BIT              54
+#define FEATURE_SPARE_55_BIT              55
+#define FEATURE_SPARE_56_BIT              56
+#define FEATURE_SPARE_57_BIT              57
+#define FEATURE_SPARE_58_BIT              58
+#define FEATURE_SPARE_59_BIT              59
+#define FEATURE_SPARE_60_BIT              60
+#define FEATURE_SPARE_61_BIT              61
+#define FEATURE_SPARE_62_BIT              62
+#define FEATURE_SPARE_63_BIT              63
+
+#define NUM_FEATURES                      64
+
+#define FEATURE_CCLK_CONTROLLER_MASK  (1 << FEATURE_CCLK_CONTROLLER_BIT)
+#define FEATURE_DATA_CALCULATION_MASK (1 << FEATURE_DATA_CALCULATION_BIT)
+#define FEATURE_THERMAL_MASK          (1 << FEATURE_THERMAL_BIT)
+#define FEATURE_PLL_POWER_DOWN_MASK   (1 << FEATURE_PLL_POWER_DOWN_BIT)
+#define FEATURE_FCLK_DPM_MASK         (1 << FEATURE_FCLK_DPM_BIT)
+#define FEATURE_GFX_DPM_MASK          (1 << FEATURE_GFX_DPM_BIT)
+#define FEATURE_DS_GFXCLK_MASK        (1 << FEATURE_DS_GFXCLK_BIT)
+#define FEATURE_DS_SOCCLK_MASK        (1 << FEATURE_DS_SOCCLK_BIT)
+#define FEATURE_DS_LCLK_MASK          (1 << FEATURE_DS_LCLK_BIT)
+#define FEATURE_RM_MASK               (1 << FEATURE_RM_BIT)
+#define FEATURE_DS_SMNCLK_MASK        (1 << FEATURE_DS_SMNCLK_BIT)
+#define FEATURE_DS_MP1CLK_MASK        (1 << FEATURE_DS_MP1CLK_BIT)
+#define FEATURE_DS_MP0CLK_MASK        (1 << FEATURE_DS_MP0CLK_BIT)
+#define FEATURE_MGCG_MASK             (1 << FEATURE_MGCG_BIT)
+#define FEATURE_DS_FUSE_SRAM_MASK     (1 << FEATURE_DS_FUSE_SRAM_BIT)
+#define FEATURE_PROCHOT_MASK          (1 << FEATURE_PROCHOT_BIT)
+#define FEATURE_CPUOFF_MASK           (1 << FEATURE_CPUOFF_BIT)
+#define FEATURE_GFX_CKS_MASK          (1 << FEATURE_GFX_CKS_BIT)
+#define FEATURE_UMC_THROTTLE_MASK     (1 << FEATURE_UMC_THROTTLE_BIT)
+#define FEATURE_DF_THROTTLE_MASK      (1 << FEATURE_DF_THROTTLE_BIT)
+#define FEATURE_SOC_DPM_MASK          (1 << FEATURE_SOC_DPM_BIT)
+
+typedef struct {
+       // MP1_EXT_SCRATCH0
+       uint32_t SPARE1            : 4;
+       uint32_t SPARE2            : 4;
+       uint32_t SPARE3            : 4;
+       uint32_t CurrLevel_LCLK    : 4;
+       uint32_t CurrLevel_MP0CLK  : 4;
+       uint32_t CurrLevel_FCLK    : 4;
+       uint32_t CurrLevel_SOCCLK  : 4;
+       uint32_t CurrLevel_DCEFCLK : 4;
+       // MP1_EXT_SCRATCH1
+       uint32_t SPARE4            : 4;
+       uint32_t SPARE5            : 4;
+       uint32_t SPARE6            : 4;
+       uint32_t TargLevel_LCLK    : 4;
+       uint32_t TargLevel_MP0CLK  : 4;
+       uint32_t TargLevel_FCLK    : 4;
+       uint32_t TargLevel_SOCCLK  : 4;
+       uint32_t TargLevel_DCEFCLK : 4;
+       // MP1_EXT_SCRATCH2
+       uint32_t CurrLevel_SHUBCLK  : 4;
+       uint32_t TargLevel_SHUBCLK  : 4;
+       uint32_t Reserved          : 24;
+       // MP1_EXT_SCRATCH3-4
+       uint32_t Reserved2[2];
+       // MP1_EXT_SCRATCH5
+       uint32_t FeatureStatus[NUM_FEATURES / 32];
+} FwStatus_t;
+
+#pragma pack(pop)
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h
new file mode 100644 (file)
index 0000000..6e60887
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef SMU_11_8_0_PPSMC_H
+#define SMU_11_8_0_PPSMC_H
+
+// SMU Response Codes:
+#define PPSMC_Result_OK                    0x1
+#define PPSMC_Result_Failed                0xFF
+#define PPSMC_Result_UnknownCmd            0xFE
+#define PPSMC_Result_CmdRejectedPrereq     0xFD
+#define PPSMC_Result_CmdRejectedBusy       0xFC
+
+// Message Definitions:
+#define PPSMC_MSG_TestMessage                           0x1
+#define PPSMC_MSG_GetSmuVersion                         0x2
+#define PPSMC_MSG_GetDriverIfVersion                    0x3
+#define PPSMC_MSG_SetDriverTableDramAddrHigh            0x4
+#define PPSMC_MSG_SetDriverTableDramAddrLow             0x5
+#define PPSMC_MSG_TransferTableSmu2Dram                 0x6
+#define PPSMC_MSG_TransferTableDram2Smu                 0x7
+#define PPSMC_MSG_Rsvd1                                 0xA
+#define PPSMC_MSG_RequestCorePstate                     0xB
+#define PPSMC_MSG_QueryCorePstate                       0xC
+#define PPSMC_MSG_Rsvd2                                 0xD
+#define PPSMC_MSG_RequestGfxclk                         0xE
+#define PPSMC_MSG_QueryGfxclk                           0xF
+#define PPSMC_MSG_QueryVddcrSocClock                    0x11
+#define PPSMC_MSG_QueryDfPstate                         0x13
+#define PPSMC_MSG_Rsvd3                                 0x14
+#define PPSMC_MSG_ConfigureS3PwrOffRegisterAddressHigh  0x16
+#define PPSMC_MSG_ConfigureS3PwrOffRegisterAddressLow   0x17
+#define PPSMC_MSG_RequestActiveWgp                      0x18
+#define PPSMC_MSG_SetMinDeepSleepGfxclkFreq             0x19
+#define PPSMC_MSG_SetMaxDeepSleepDfllGfxDiv             0x1A
+#define PPSMC_MSG_StartTelemetryReporting               0x1B
+#define PPSMC_MSG_StopTelemetryReporting                0x1C
+#define PPSMC_MSG_ClearTelemetryMax                     0x1D
+#define PPSMC_MSG_QueryActiveWgp                        0x1E
+#define PPSMC_MSG_SetCoreEnableMask                     0x2C
+#define PPSMC_MSG_InitiateGcRsmuSoftReset               0x2E
+#define PPSMC_MSG_GfxCacWeightOperation                 0x2F
+#define PPSMC_MSG_L3CacWeightOperation                  0x30
+#define PPSMC_MSG_PackCoreCacWeight                     0x31
+#define PPSMC_MSG_SetDriverTableVMID                    0x34
+#define PPSMC_MSG_SetSoftMinCclk                        0x35
+#define PPSMC_MSG_SetSoftMaxCclk                        0x36
+#define PPSMC_Message_Count                             0x37
+
+#endif
index ebe67214280851f11945546c88c9bf34d6f2cdaf..71afc2d20b1238d8bf4496c059a2a2d3b21031ff 100644 (file)
@@ -36,6 +36,7 @@
 #include "vangogh_ppt.h"
 #include "aldebaran_ppt.h"
 #include "yellow_carp_ppt.h"
+#include "cyan_skillfish_ppt.h"
 #include "amd_pcie.h"
 
 /*
@@ -416,6 +417,15 @@ static void smu_restore_dpm_user_profile(struct smu_context *smu)
                }
        }
 
+       /* Restore user customized OD settings */
+       if (smu->user_dpm_profile.user_od) {
+               if (smu->ppt_funcs->restore_user_od_settings) {
+                       ret = smu->ppt_funcs->restore_user_od_settings(smu);
+                       if (ret)
+                               dev_err(smu->adev->dev, "Failed to upload customized OD settings\n");
+               }
+       }
+
        /* Disable restore flag */
        smu->user_dpm_profile.flags &= ~SMU_DPM_USER_PROFILE_RESTORE;
 }
@@ -588,6 +598,9 @@ static int smu_set_funcs(struct amdgpu_device *adev)
        case CHIP_YELLOW_CARP:
                yellow_carp_set_ppt_funcs(smu);
                break;
+       case CHIP_CYAN_SKILLFISH:
+               cyan_skillfish_set_ppt_funcs(smu);
+               break;
        default:
                return -EINVAL;
        }
index 0138c982dfd3100e887798641b75b8975dd0e928..f9b2e16f64311979197ba4bc3f851a2ad7b1c156 100644 (file)
@@ -27,6 +27,7 @@ SMU11_MGR = arcturus_ppt.o \
            navi10_ppt.o \
            sienna_cichlid_ppt.o \
            vangogh_ppt.o \
+           cyan_skillfish_ppt.o \
            smu_v11_0.o
 
 AMD_SWSMU_SMU11MGR = $(addprefix $(AMD_SWSMU_PATH)/smu11/,$(SMU11_MGR))
index 094df6f87cfc4105cd5318373cc66807d40a9f34..6ec8492f71f593ff82109dbb5ab2218257bbbc8e 100644 (file)
@@ -1936,197 +1936,77 @@ static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
        return ret;
 }
 
-static void arcturus_fill_i2c_req(SwI2cRequest_t  *req, bool write,
-                                 uint8_t address, uint32_t numbytes,
-                                 uint8_t *data)
-{
-       int i;
-
-       req->I2CcontrollerPort = 0;
-       req->I2CSpeed = 2;
-       req->SlaveAddress = address;
-       req->NumCmds = numbytes;
-
-       for (i = 0; i < numbytes; i++) {
-               SwI2cCmd_t *cmd =  &req->SwI2cCmds[i];
-
-               /* First 2 bytes are always write for lower 2b EEPROM address */
-               if (i < 2)
-                       cmd->Cmd = 1;
-               else
-                       cmd->Cmd = write;
-
-
-               /* Add RESTART for read  after address filled */
-               cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0;
-
-               /* Add STOP in the end */
-               cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0;
-
-               /* Fill with data regardless if read or write to simplify code */
-               cmd->RegisterAddr = data[i];
-       }
-}
-
-static int arcturus_i2c_read_data(struct i2c_adapter *control,
-                                              uint8_t address,
-                                              uint8_t *data,
-                                              uint32_t numbytes)
+static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
+                            struct i2c_msg *msg, int num_msgs)
 {
-       uint32_t  i, ret = 0;
-       SwI2cRequest_t req;
-       struct amdgpu_device *adev = to_amdgpu_device(control);
+       struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
        struct smu_table_context *smu_table = &adev->smu.smu_table;
        struct smu_table *table = &smu_table->driver_table;
+       SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
+       int i, j, r, c;
+       u16 dir;
 
-       if (numbytes > MAX_SW_I2C_COMMANDS) {
-               dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
-                       numbytes, MAX_SW_I2C_COMMANDS);
-               return -EINVAL;
-       }
-
-       memset(&req, 0, sizeof(req));
-       arcturus_fill_i2c_req(&req, false, address, numbytes, data);
-
-       mutex_lock(&adev->smu.mutex);
-       /* Now read data starting with that address */
-       ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req,
-                                       true);
-       mutex_unlock(&adev->smu.mutex);
-
-       if (!ret) {
-               SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr;
-
-               /* Assume SMU  fills res.SwI2cCmds[i].Data with read bytes */
-               for (i = 0; i < numbytes; i++)
-                       data[i] = res->SwI2cCmds[i].Data;
-
-               dev_dbg(adev->dev, "arcturus_i2c_read_data, address = %x, bytes = %d, data :",
-                                 (uint16_t)address, numbytes);
-
-               print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
-                              8, 1, data, numbytes, false);
-       } else
-               dev_err(adev->dev, "arcturus_i2c_read_data - error occurred :%x", ret);
+       req = kzalloc(sizeof(*req), GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
 
-       return ret;
-}
+       req->I2CcontrollerPort = 0;
+       req->I2CSpeed = I2C_SPEED_FAST_400K;
+       req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
+       dir = msg[0].flags & I2C_M_RD;
+
+       for (c = i = 0; i < num_msgs; i++) {
+               for (j = 0; j < msg[i].len; j++, c++) {
+                       SwI2cCmd_t *cmd = &req->SwI2cCmds[c];
+
+                       if (!(msg[i].flags & I2C_M_RD)) {
+                               /* write */
+                               cmd->Cmd = I2C_CMD_WRITE;
+                               cmd->RegisterAddr = msg[i].buf[j];
+                       }
 
-static int arcturus_i2c_write_data(struct i2c_adapter *control,
-                                               uint8_t address,
-                                               uint8_t *data,
-                                               uint32_t numbytes)
-{
-       uint32_t ret;
-       SwI2cRequest_t req;
-       struct amdgpu_device *adev = to_amdgpu_device(control);
+                       if ((dir ^ msg[i].flags) & I2C_M_RD) {
+                               /* The direction changes.
+                                */
+                               dir = msg[i].flags & I2C_M_RD;
+                               cmd->CmdConfig |= CMDCONFIG_RESTART_MASK;
+                       }
 
-       if (numbytes > MAX_SW_I2C_COMMANDS) {
-               dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
-                       numbytes, MAX_SW_I2C_COMMANDS);
-               return -EINVAL;
+                       req->NumCmds++;
+
+                       /*
+                        * Insert STOP if we are at the last byte of either last
+                        * message for the transaction or the client explicitly
+                        * requires a STOP at this particular message.
+                        */
+                       if ((j == msg[i].len - 1) &&
+                           ((i == num_msgs - 1) || (msg[i].flags & I2C_M_STOP))) {
+                               cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK;
+                               cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
+                       }
+               }
        }
-
-       memset(&req, 0, sizeof(req));
-       arcturus_fill_i2c_req(&req, true, address, numbytes, data);
-
        mutex_lock(&adev->smu.mutex);
-       ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true);
+       r = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
        mutex_unlock(&adev->smu.mutex);
+       if (r)
+               goto fail;
 
-       if (!ret) {
-               dev_dbg(adev->dev, "arcturus_i2c_write(), address = %x, bytes = %d , data: ",
-                                        (uint16_t)address, numbytes);
-
-               print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
-                              8, 1, data, numbytes, false);
-               /*
-                * According to EEPROM spec there is a MAX of 10 ms required for
-                * EEPROM to flush internal RX buffer after STOP was issued at the
-                * end of write transaction. During this time the EEPROM will not be
-                * responsive to any more commands - so wait a bit more.
-                */
-               msleep(10);
-
-       } else
-               dev_err(adev->dev, "arcturus_i2c_write- error occurred :%x", ret);
-
-       return ret;
-}
-
-static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
-                             struct i2c_msg *msgs, int num)
-{
-       uint32_t  i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0;
-       uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 };
-
-       for (i = 0; i < num; i++) {
-               /*
-                * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at
-                * once and hence the data needs to be spliced into chunks and sent each
-                * chunk separately
-                */
-               data_size = msgs[i].len - 2;
-               data_chunk_size = MAX_SW_I2C_COMMANDS - 2;
-               next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff);
-               data_ptr = msgs[i].buf + 2;
-
-               for (j = 0; j < data_size / data_chunk_size; j++) {
-                       /* Insert the EEPROM dest addess, bits 0-15 */
-                       data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
-                       data_chunk[1] = (next_eeprom_addr & 0xff);
-
-                       if (msgs[i].flags & I2C_M_RD) {
-                               ret = arcturus_i2c_read_data(i2c_adap,
-                                                            (uint8_t)msgs[i].addr,
-                                                            data_chunk, MAX_SW_I2C_COMMANDS);
-
-                               memcpy(data_ptr, data_chunk + 2, data_chunk_size);
-                       } else {
-
-                               memcpy(data_chunk + 2, data_ptr, data_chunk_size);
-
-                               ret = arcturus_i2c_write_data(i2c_adap,
-                                                             (uint8_t)msgs[i].addr,
-                                                             data_chunk, MAX_SW_I2C_COMMANDS);
-                       }
-
-                       if (ret) {
-                               num = -EIO;
-                               goto fail;
-                       }
-
-                       next_eeprom_addr += data_chunk_size;
-                       data_ptr += data_chunk_size;
+       for (c = i = 0; i < num_msgs; i++) {
+               if (!(msg[i].flags & I2C_M_RD)) {
+                       c += msg[i].len;
+                       continue;
                }
+               for (j = 0; j < msg[i].len; j++, c++) {
+                       SwI2cCmd_t *cmd = &res->SwI2cCmds[c];
 
-               if (data_size % data_chunk_size) {
-                       data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
-                       data_chunk[1] = (next_eeprom_addr & 0xff);
-
-                       if (msgs[i].flags & I2C_M_RD) {
-                               ret = arcturus_i2c_read_data(i2c_adap,
-                                                            (uint8_t)msgs[i].addr,
-                                                            data_chunk, (data_size % data_chunk_size) + 2);
-
-                               memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size);
-                       } else {
-                               memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size);
-
-                               ret = arcturus_i2c_write_data(i2c_adap,
-                                                             (uint8_t)msgs[i].addr,
-                                                             data_chunk, (data_size % data_chunk_size) + 2);
-                       }
-
-                       if (ret) {
-                               num = -EIO;
-                               goto fail;
-                       }
+                       msg[i].buf[j] = cmd->Data;
                }
        }
-
+       r = num_msgs;
 fail:
-       return num;
+       kfree(req);
+       return r;
 }
 
 static u32 arcturus_i2c_func(struct i2c_adapter *adap)
@@ -2140,15 +2020,25 @@ static const struct i2c_algorithm arcturus_i2c_algo = {
        .functionality = arcturus_i2c_func,
 };
 
+
+static const struct i2c_adapter_quirks arcturus_i2c_control_quirks = {
+       .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR | I2C_AQ_NO_ZERO_LEN,
+       .max_read_len  = MAX_SW_I2C_COMMANDS,
+       .max_write_len = MAX_SW_I2C_COMMANDS,
+       .max_comb_1st_msg_len = 2,
+       .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
+};
+
 static int arcturus_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
 {
        struct amdgpu_device *adev = to_amdgpu_device(control);
        int res;
 
        control->owner = THIS_MODULE;
-       control->class = I2C_CLASS_SPD;
+       control->class = I2C_CLASS_HWMON;
        control->dev.parent = &adev->pdev->dev;
        control->algo = &arcturus_i2c_algo;
+       control->quirks = &arcturus_i2c_control_quirks;
        snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
 
        res = i2c_add_adapter(control);
@@ -2288,7 +2178,9 @@ static void arcturus_log_thermal_throttling_event(struct smu_context *smu)
 
        dev_warn(adev->dev, "WARN: GPU thermal throttling temperature reached, expect performance decrease. %s.\n",
                        log_buf);
-       kgd2kfd_smi_event_throttle(smu->adev->kfd.dev, throttler_status);
+       kgd2kfd_smi_event_throttle(smu->adev->kfd.dev,
+               smu_cmn_get_indep_throttler_status(throttler_status,
+                                                  arcturus_throttler_map));
 }
 
 static uint16_t arcturus_get_current_pcie_link_speed(struct smu_context *smu)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c
new file mode 100644 (file)
index 0000000..b05f954
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#define SWSMU_CODE_LAYER_L2
+
+#include "amdgpu.h"
+#include "amdgpu_smu.h"
+#include "smu_v11_0.h"
+#include "smu11_driver_if_cyan_skillfish.h"
+#include "cyan_skillfish_ppt.h"
+#include "smu_v11_8_ppsmc.h"
+#include "smu_v11_8_pmfw.h"
+#include "smu_cmn.h"
+#include "soc15_common.h"
+
+/*
+ * DO NOT use these for err/warn/info/debug messages.
+ * Use dev_err, dev_warn, dev_info and dev_dbg instead.
+ * They are more MGPU friendly.
+ */
+
+#undef pr_err
+#undef pr_warn
+#undef pr_info
+#undef pr_debug
+
+static struct cmn2asic_msg_mapping cyan_skillfish_message_map[SMU_MSG_MAX_COUNT] = {
+       MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage,                  0),
+       MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetSmuVersion,                0),
+       MSG_MAP(GetDriverIfVersion,             PPSMC_MSG_GetDriverIfVersion,           0),
+       MSG_MAP(SetDriverDramAddrHigh,          PPSMC_MSG_SetDriverTableDramAddrHigh,   0),
+       MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverTableDramAddrLow,    0),
+       MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram,        0),
+       MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu,        0),
+};
+
+static const struct pptable_funcs cyan_skillfish_ppt_funcs = {
+
+       .check_fw_status = smu_v11_0_check_fw_status,
+       .check_fw_version = smu_v11_0_check_fw_version,
+       .init_power = smu_v11_0_init_power,
+       .fini_power = smu_v11_0_fini_power,
+       .register_irq_handler = smu_v11_0_register_irq_handler,
+       .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
+       .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
+       .send_smc_msg = smu_cmn_send_smc_msg,
+       .set_driver_table_location = smu_v11_0_set_driver_table_location,
+       .interrupt_work = smu_v11_0_interrupt_work,
+};
+
+void cyan_skillfish_set_ppt_funcs(struct smu_context *smu)
+{
+       smu->ppt_funcs = &cyan_skillfish_ppt_funcs;
+       smu->message_map = cyan_skillfish_message_map;
+       smu->is_apu = true;
+}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.h
new file mode 100644 (file)
index 0000000..76cd722
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __CYAN_SKILLFISH_PPT_H__
+#define __CYAN_SKILLFISH_PPT_H__
+
+extern void cyan_skillfish_set_ppt_funcs(struct smu_context *smu);
+
+#endif
index 1ba42b69ce7424bc11b4bf26d40af8da54bf3fe4..d7722c229dddef05e47e5deda960f9c69564f03b 100644 (file)
@@ -2294,41 +2294,52 @@ static int navi10_set_default_od_settings(struct smu_context *smu)
                (OverDriveTable_t *)smu->smu_table.overdrive_table;
        OverDriveTable_t *boot_od_table =
                (OverDriveTable_t *)smu->smu_table.boot_overdrive_table;
+       OverDriveTable_t *user_od_table =
+               (OverDriveTable_t *)smu->smu_table.user_overdrive_table;
        int ret = 0;
 
-       ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, false);
+       /*
+        * 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, 0, (void *)boot_od_table, false);
        if (ret) {
                dev_err(smu->adev->dev, "Failed to get overdrive table!\n");
                return ret;
        }
 
-       if (!od_table->GfxclkVolt1) {
+       if (!boot_od_table->GfxclkVolt1) {
                ret = navi10_overdrive_get_gfx_clk_base_voltage(smu,
-                                                               &od_table->GfxclkVolt1,
-                                                               od_table->GfxclkFreq1);
+                                                               &boot_od_table->GfxclkVolt1,
+                                                               boot_od_table->GfxclkFreq1);
                if (ret)
                        return ret;
        }
 
-       if (!od_table->GfxclkVolt2) {
+       if (!boot_od_table->GfxclkVolt2) {
                ret = navi10_overdrive_get_gfx_clk_base_voltage(smu,
-                                                               &od_table->GfxclkVolt2,
-                                                               od_table->GfxclkFreq2);
+                                                               &boot_od_table->GfxclkVolt2,
+                                                               boot_od_table->GfxclkFreq2);
                if (ret)
                        return ret;
        }
 
-       if (!od_table->GfxclkVolt3) {
+       if (!boot_od_table->GfxclkVolt3) {
                ret = navi10_overdrive_get_gfx_clk_base_voltage(smu,
-                                                               &od_table->GfxclkVolt3,
-                                                               od_table->GfxclkFreq3);
+                                                               &boot_od_table->GfxclkVolt3,
+                                                               boot_od_table->GfxclkFreq3);
                if (ret)
                        return ret;
        }
 
-       memcpy(boot_od_table, od_table, sizeof(OverDriveTable_t));
+       navi10_dump_od_table(smu, boot_od_table);
 
-       navi10_dump_od_table(smu, od_table);
+       memcpy(od_table, boot_od_table, sizeof(OverDriveTable_t));
+       memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t));
 
        return 0;
 }
@@ -2429,11 +2440,20 @@ static int navi10_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABL
                memcpy(table_context->overdrive_table, table_context->boot_overdrive_table, sizeof(OverDriveTable_t));
                break;
        case PP_OD_COMMIT_DPM_TABLE:
-               navi10_dump_od_table(smu, od_table);
-               ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, true);
-               if (ret) {
-                       dev_err(smu->adev->dev, "Failed to import overdrive table!\n");
-                       return ret;
+               if (memcmp(od_table, table_context->user_overdrive_table, sizeof(OverDriveTable_t))) {
+                       navi10_dump_od_table(smu, od_table);
+                       ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, true);
+                       if (ret) {
+                               dev_err(smu->adev->dev, "Failed to import overdrive table!\n");
+                               return ret;
+                       }
+                       memcpy(table_context->user_overdrive_table, od_table, sizeof(OverDriveTable_t));
+                       smu->user_dpm_profile.user_od = true;
+
+                       if (!memcmp(table_context->user_overdrive_table,
+                                   table_context->boot_overdrive_table,
+                                   sizeof(OverDriveTable_t)))
+                               smu->user_dpm_profile.user_od = false;
                }
                break;
        case PP_OD_EDIT_VDDC_CURVE:
@@ -2735,6 +2755,122 @@ static ssize_t navi10_get_legacy_gpu_metrics(struct smu_context *smu,
        return sizeof(struct gpu_metrics_v1_3);
 }
 
+static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
+                          struct i2c_msg *msg, int num_msgs)
+{
+       struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
+       struct smu_table_context *smu_table = &adev->smu.smu_table;
+       struct smu_table *table = &smu_table->driver_table;
+       SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
+       int i, j, r, c;
+       u16 dir;
+
+       req = kzalloc(sizeof(*req), GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
+
+       req->I2CcontrollerPort = 0;
+       req->I2CSpeed = I2C_SPEED_FAST_400K;
+       req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
+       dir = msg[0].flags & I2C_M_RD;
+
+       for (c = i = 0; i < num_msgs; i++) {
+               for (j = 0; j < msg[i].len; j++, c++) {
+                       SwI2cCmd_t *cmd = &req->SwI2cCmds[c];
+
+                       if (!(msg[i].flags & I2C_M_RD)) {
+                               /* write */
+                               cmd->Cmd = I2C_CMD_WRITE;
+                               cmd->RegisterAddr = msg[i].buf[j];
+                       }
+
+                       if ((dir ^ msg[i].flags) & I2C_M_RD) {
+                               /* The direction changes.
+                                */
+                               dir = msg[i].flags & I2C_M_RD;
+                               cmd->CmdConfig |= CMDCONFIG_RESTART_MASK;
+                       }
+
+                       req->NumCmds++;
+
+                       /*
+                        * Insert STOP if we are at the last byte of either last
+                        * message for the transaction or the client explicitly
+                        * requires a STOP at this particular message.
+                        */
+                       if ((j == msg[i].len - 1) &&
+                           ((i == num_msgs - 1) || (msg[i].flags & I2C_M_STOP))) {
+                               cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK;
+                               cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
+                       }
+               }
+       }
+       mutex_lock(&adev->smu.mutex);
+       r = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
+       mutex_unlock(&adev->smu.mutex);
+       if (r)
+               goto fail;
+
+       for (c = i = 0; i < num_msgs; i++) {
+               if (!(msg[i].flags & I2C_M_RD)) {
+                       c += msg[i].len;
+                       continue;
+               }
+               for (j = 0; j < msg[i].len; j++, c++) {
+                       SwI2cCmd_t *cmd = &res->SwI2cCmds[c];
+
+                       msg[i].buf[j] = cmd->Data;
+               }
+       }
+       r = num_msgs;
+fail:
+       kfree(req);
+       return r;
+}
+
+static u32 navi10_i2c_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+
+static const struct i2c_algorithm navi10_i2c_algo = {
+       .master_xfer = navi10_i2c_xfer,
+       .functionality = navi10_i2c_func,
+};
+
+static const struct i2c_adapter_quirks navi10_i2c_control_quirks = {
+       .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR | I2C_AQ_NO_ZERO_LEN,
+       .max_read_len  = MAX_SW_I2C_COMMANDS,
+       .max_write_len = MAX_SW_I2C_COMMANDS,
+       .max_comb_1st_msg_len = 2,
+       .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
+};
+
+static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
+{
+       struct amdgpu_device *adev = to_amdgpu_device(control);
+       int res;
+
+       control->owner = THIS_MODULE;
+       control->class = I2C_CLASS_HWMON;
+       control->dev.parent = &adev->pdev->dev;
+       control->algo = &navi10_i2c_algo;
+       snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
+       control->quirks = &navi10_i2c_control_quirks;
+
+       res = i2c_add_adapter(control);
+       if (res)
+               DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
+
+       return res;
+}
+
+static void navi10_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control)
+{
+       i2c_del_adapter(control);
+}
+
 static ssize_t navi10_get_gpu_metrics(struct smu_context *smu,
                                      void **table)
 {
@@ -3078,6 +3214,8 @@ static const struct pptable_funcs navi10_ppt_funcs = {
        .set_default_dpm_table = navi10_set_default_dpm_table,
        .dpm_set_vcn_enable = navi10_dpm_set_vcn_enable,
        .dpm_set_jpeg_enable = navi10_dpm_set_jpeg_enable,
+       .i2c_init = navi10_i2c_control_init,
+       .i2c_fini = navi10_i2c_control_fini,
        .print_clk_levels = navi10_print_clk_levels,
        .force_clk_levels = navi10_force_clk_levels,
        .populate_umd_state_clk = navi10_populate_umd_state_clk,
@@ -3144,6 +3282,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
        .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
        .set_default_od_settings = navi10_set_default_od_settings,
        .od_edit_dpm_table = navi10_od_edit_dpm_table,
+       .restore_user_od_settings = smu_v11_0_restore_user_od_settings,
        .run_btc = navi10_run_btc,
        .set_power_source = smu_v11_0_set_power_source,
        .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
index c751f717a0daff49620bcd850906bb362df1f665..90e40aacb8f690c14402dcb86d91312f8b6940c3 100644 (file)
@@ -489,6 +489,26 @@ err0_out:
        return -ENOMEM;
 }
 
+static uint32_t sienna_cichlid_get_throttler_status_locked(struct smu_context *smu)
+{
+       struct smu_table_context *smu_table= &smu->smu_table;
+       SmuMetricsExternal_t *metrics_ext =
+               (SmuMetricsExternal_t *)(smu_table->metrics_table);
+       uint32_t throttler_status = 0;
+       int i;
+
+       if ((smu->adev->asic_type == CHIP_SIENNA_CICHLID) &&
+            (smu->smc_fw_version >= 0x3A4300)) {
+               for (i = 0; i < THROTTLER_COUNT; i++)
+                       throttler_status |=
+                               (metrics_ext->SmuMetrics_V2.ThrottlingPercentage[i] ? 1U << i : 0);
+       } else {
+               throttler_status = metrics_ext->SmuMetrics.ThrottlerStatus;
+       }
+
+       return throttler_status;
+}
+
 static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu,
                                               MetricsMember_t member,
                                               uint32_t *value)
@@ -496,6 +516,11 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu,
        struct smu_table_context *smu_table= &smu->smu_table;
        SmuMetrics_t *metrics =
                &(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics);
+       SmuMetrics_V2_t *metrics_v2 =
+               &(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics_V2);
+       bool use_metrics_v2 = ((smu->adev->asic_type == CHIP_SIENNA_CICHLID) &&
+               (smu->smc_fw_version >= 0x3A4300)) ? true : false;
+       uint16_t average_gfx_activity;
        int ret = 0;
 
        mutex_lock(&smu->metrics_lock);
@@ -510,78 +535,96 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu,
 
        switch (member) {
        case METRICS_CURR_GFXCLK:
-               *value = metrics->CurrClock[PPCLK_GFXCLK];
+               *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_GFXCLK] :
+                       metrics->CurrClock[PPCLK_GFXCLK];
                break;
        case METRICS_CURR_SOCCLK:
-               *value = metrics->CurrClock[PPCLK_SOCCLK];
+               *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_SOCCLK] :
+                       metrics->CurrClock[PPCLK_SOCCLK];
                break;
        case METRICS_CURR_UCLK:
-               *value = metrics->CurrClock[PPCLK_UCLK];
+               *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_UCLK] :
+                       metrics->CurrClock[PPCLK_UCLK];
                break;
        case METRICS_CURR_VCLK:
-               *value = metrics->CurrClock[PPCLK_VCLK_0];
+               *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_VCLK_0] :
+                       metrics->CurrClock[PPCLK_VCLK_0];
                break;
        case METRICS_CURR_VCLK1:
-               *value = metrics->CurrClock[PPCLK_VCLK_1];
+               *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_VCLK_1] :
+                       metrics->CurrClock[PPCLK_VCLK_1];
                break;
        case METRICS_CURR_DCLK:
-               *value = metrics->CurrClock[PPCLK_DCLK_0];
+               *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_DCLK_0] :
+                       metrics->CurrClock[PPCLK_DCLK_0];
                break;
        case METRICS_CURR_DCLK1:
-               *value = metrics->CurrClock[PPCLK_DCLK_1];
+               *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_DCLK_1] :
+                       metrics->CurrClock[PPCLK_DCLK_1];
                break;
        case METRICS_CURR_DCEFCLK:
-               *value = metrics->CurrClock[PPCLK_DCEFCLK];
+               *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_DCEFCLK] :
+                       metrics->CurrClock[PPCLK_DCEFCLK];
                break;
        case METRICS_CURR_FCLK:
-               *value = metrics->CurrClock[PPCLK_FCLK];
+               *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_FCLK] :
+                       metrics->CurrClock[PPCLK_FCLK];
                break;
        case METRICS_AVERAGE_GFXCLK:
-               if (metrics->AverageGfxActivity <= SMU_11_0_7_GFX_BUSY_THRESHOLD)
-                       *value = metrics->AverageGfxclkFrequencyPostDs;
+               average_gfx_activity = use_metrics_v2 ? metrics_v2->AverageGfxActivity :
+                       metrics->AverageGfxActivity;
+               if (average_gfx_activity <= SMU_11_0_7_GFX_BUSY_THRESHOLD)
+                       *value = use_metrics_v2 ? metrics_v2->AverageGfxclkFrequencyPostDs :
+                               metrics->AverageGfxclkFrequencyPostDs;
                else
-                       *value = metrics->AverageGfxclkFrequencyPreDs;
+                       *value = use_metrics_v2 ? metrics_v2->AverageGfxclkFrequencyPreDs :
+                               metrics->AverageGfxclkFrequencyPreDs;
                break;
        case METRICS_AVERAGE_FCLK:
-               *value = metrics->AverageFclkFrequencyPostDs;
+               *value = use_metrics_v2 ? metrics_v2->AverageFclkFrequencyPostDs :
+                       metrics->AverageFclkFrequencyPostDs;
                break;
        case METRICS_AVERAGE_UCLK:
-               *value = metrics->AverageUclkFrequencyPostDs;
+               *value = use_metrics_v2 ? metrics_v2->AverageUclkFrequencyPostDs :
+                       metrics->AverageUclkFrequencyPostDs;
                break;
        case METRICS_AVERAGE_GFXACTIVITY:
-               *value = metrics->AverageGfxActivity;
+               *value = use_metrics_v2 ? metrics_v2->AverageGfxActivity :
+                       metrics->AverageGfxActivity;
                break;
        case METRICS_AVERAGE_MEMACTIVITY:
-               *value = metrics->AverageUclkActivity;
+               *value = use_metrics_v2 ? metrics_v2->AverageUclkActivity :
+                       metrics->AverageUclkActivity;
                break;
        case METRICS_AVERAGE_SOCKETPOWER:
-               *value = metrics->AverageSocketPower << 8;
+               *value = use_metrics_v2 ? metrics_v2->AverageSocketPower << 8 :
+                       metrics->AverageSocketPower << 8;
                break;
        case METRICS_TEMPERATURE_EDGE:
-               *value = metrics->TemperatureEdge *
+               *value = (use_metrics_v2 ? metrics_v2->TemperatureEdge : metrics->TemperatureEdge) *
                        SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
                break;
        case METRICS_TEMPERATURE_HOTSPOT:
-               *value = metrics->TemperatureHotspot *
+               *value = (use_metrics_v2 ? metrics_v2->TemperatureHotspot : metrics->TemperatureHotspot) *
                        SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
                break;
        case METRICS_TEMPERATURE_MEM:
-               *value = metrics->TemperatureMem *
+               *value = (use_metrics_v2 ? metrics_v2->TemperatureMem : metrics->TemperatureMem) *
                        SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
                break;
        case METRICS_TEMPERATURE_VRGFX:
-               *value = metrics->TemperatureVrGfx *
+               *value = (use_metrics_v2 ? metrics_v2->TemperatureVrGfx : metrics->TemperatureVrGfx) *
                        SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
                break;
        case METRICS_TEMPERATURE_VRSOC:
-               *value = metrics->TemperatureVrSoc *
+               *value = (use_metrics_v2 ? metrics_v2->TemperatureVrSoc : metrics->TemperatureVrSoc) *
                        SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
                break;
        case METRICS_THROTTLER_STATUS:
-               *value = metrics->ThrottlerStatus;
+               *value = sienna_cichlid_get_throttler_status_locked(smu);
                break;
        case METRICS_CURR_FANSPEED:
-               *value = metrics->CurrFanSpeed;
+               *value = use_metrics_v2 ? metrics_v2->CurrFanSpeed : metrics->CurrFanSpeed;
                break;
        default:
                *value = UINT_MAX;
@@ -1911,18 +1954,29 @@ static int sienna_cichlid_set_default_od_settings(struct smu_context *smu)
                (OverDriveTable_t *)smu->smu_table.overdrive_table;
        OverDriveTable_t *boot_od_table =
                (OverDriveTable_t *)smu->smu_table.boot_overdrive_table;
+       OverDriveTable_t *user_od_table =
+               (OverDriveTable_t *)smu->smu_table.user_overdrive_table;
        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,
-                                  0, (void *)od_table, false);
+                                  0, (void *)boot_od_table, false);
        if (ret) {
                dev_err(smu->adev->dev, "Failed to get overdrive table!\n");
                return ret;
        }
 
-       memcpy(boot_od_table, od_table, sizeof(OverDriveTable_t));
+       sienna_cichlid_dump_od_table(smu, boot_od_table);
 
-       sienna_cichlid_dump_od_table(smu, od_table);
+       memcpy(od_table, boot_od_table, sizeof(OverDriveTable_t));
+       memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t));
 
        return 0;
 }
@@ -2085,13 +2139,20 @@ static int sienna_cichlid_od_edit_dpm_table(struct smu_context *smu,
                fallthrough;
 
        case PP_OD_COMMIT_DPM_TABLE:
-               sienna_cichlid_dump_od_table(smu, od_table);
+               if (memcmp(od_table, table_context->user_overdrive_table, sizeof(OverDriveTable_t))) {
+                       sienna_cichlid_dump_od_table(smu, od_table);
+                       ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, true);
+                       if (ret) {
+                               dev_err(smu->adev->dev, "Failed to import overdrive table!\n");
+                               return ret;
+                       }
+                       memcpy(table_context->user_overdrive_table, od_table, sizeof(OverDriveTable_t));
+                       smu->user_dpm_profile.user_od = true;
 
-               ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE,
-                                          0, (void *)od_table, true);
-               if (ret) {
-                       dev_err(smu->adev->dev, "Failed to import overdrive table!\n");
-                       return ret;
+                       if (!memcmp(table_context->user_overdrive_table,
+                                   table_context->boot_overdrive_table,
+                                   sizeof(OverDriveTable_t)))
+                               smu->user_dpm_profile.user_od = false;
                }
                break;
 
@@ -3442,197 +3503,77 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu)
        dev_info(smu->adev->dev, "MmHubPadding[7] = 0x%x\n", pptable->MmHubPadding[7]);
 }
 
-static void sienna_cichlid_fill_i2c_req(SwI2cRequest_t  *req, bool write,
-                                 uint8_t address, uint32_t numbytes,
-                                 uint8_t *data)
-{
-       int i;
-
-       req->I2CcontrollerPort = 1;
-       req->I2CSpeed = 2;
-       req->SlaveAddress = address;
-       req->NumCmds = numbytes;
-
-       for (i = 0; i < numbytes; i++) {
-               SwI2cCmd_t *cmd =  &req->SwI2cCmds[i];
-
-               /* First 2 bytes are always write for lower 2b EEPROM address */
-               if (i < 2)
-                       cmd->CmdConfig = CMDCONFIG_READWRITE_MASK;
-               else
-                       cmd->CmdConfig = write ? CMDCONFIG_READWRITE_MASK : 0;
-
-
-               /* Add RESTART for read  after address filled */
-               cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0;
-
-               /* Add STOP in the end */
-               cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0;
-
-               /* Fill with data regardless if read or write to simplify code */
-               cmd->ReadWriteData = data[i];
-       }
-}
-
-static int sienna_cichlid_i2c_read_data(struct i2c_adapter *control,
-                                              uint8_t address,
-                                              uint8_t *data,
-                                              uint32_t numbytes)
+static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap,
+                                  struct i2c_msg *msg, int num_msgs)
 {
-       uint32_t  i, ret = 0;
-       SwI2cRequest_t req;
-       struct amdgpu_device *adev = to_amdgpu_device(control);
+       struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
        struct smu_table_context *smu_table = &adev->smu.smu_table;
        struct smu_table *table = &smu_table->driver_table;
+       SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
+       int i, j, r, c;
+       u16 dir;
 
-       if (numbytes > MAX_SW_I2C_COMMANDS) {
-               dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
-                       numbytes, MAX_SW_I2C_COMMANDS);
-               return -EINVAL;
-       }
-
-       memset(&req, 0, sizeof(req));
-       sienna_cichlid_fill_i2c_req(&req, false, address, numbytes, data);
-
-       mutex_lock(&adev->smu.mutex);
-       /* Now read data starting with that address */
-       ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req,
-                                       true);
-       mutex_unlock(&adev->smu.mutex);
-
-       if (!ret) {
-               SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr;
-
-               /* Assume SMU  fills res.SwI2cCmds[i].Data with read bytes */
-               for (i = 0; i < numbytes; i++)
-                       data[i] = res->SwI2cCmds[i].ReadWriteData;
-
-               dev_dbg(adev->dev, "sienna_cichlid_i2c_read_data, address = %x, bytes = %d, data :",
-                                 (uint16_t)address, numbytes);
-
-               print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
-                              8, 1, data, numbytes, false);
-       } else
-               dev_err(adev->dev, "sienna_cichlid_i2c_read_data - error occurred :%x", ret);
+       req = kzalloc(sizeof(*req), GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
 
-       return ret;
-}
+       req->I2CcontrollerPort = 1;
+       req->I2CSpeed = I2C_SPEED_FAST_400K;
+       req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
+       dir = msg[0].flags & I2C_M_RD;
+
+       for (c = i = 0; i < num_msgs; i++) {
+               for (j = 0; j < msg[i].len; j++, c++) {
+                       SwI2cCmd_t *cmd = &req->SwI2cCmds[c];
+
+                       if (!(msg[i].flags & I2C_M_RD)) {
+                               /* write */
+                               cmd->CmdConfig |= CMDCONFIG_READWRITE_MASK;
+                               cmd->ReadWriteData = msg[i].buf[j];
+                       }
 
-static int sienna_cichlid_i2c_write_data(struct i2c_adapter *control,
-                                               uint8_t address,
-                                               uint8_t *data,
-                                               uint32_t numbytes)
-{
-       uint32_t ret;
-       SwI2cRequest_t req;
-       struct amdgpu_device *adev = to_amdgpu_device(control);
+                       if ((dir ^ msg[i].flags) & I2C_M_RD) {
+                               /* The direction changes.
+                                */
+                               dir = msg[i].flags & I2C_M_RD;
+                               cmd->CmdConfig |= CMDCONFIG_RESTART_MASK;
+                       }
 
-       if (numbytes > MAX_SW_I2C_COMMANDS) {
-               dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
-                       numbytes, MAX_SW_I2C_COMMANDS);
-               return -EINVAL;
+                       req->NumCmds++;
+
+                       /*
+                        * Insert STOP if we are at the last byte of either last
+                        * message for the transaction or the client explicitly
+                        * requires a STOP at this particular message.
+                        */
+                       if ((j == msg[i].len - 1) &&
+                           ((i == num_msgs - 1) || (msg[i].flags & I2C_M_STOP))) {
+                               cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK;
+                               cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
+                       }
+               }
        }
-
-       memset(&req, 0, sizeof(req));
-       sienna_cichlid_fill_i2c_req(&req, true, address, numbytes, data);
-
        mutex_lock(&adev->smu.mutex);
-       ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true);
+       r = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
        mutex_unlock(&adev->smu.mutex);
+       if (r)
+               goto fail;
 
-       if (!ret) {
-               dev_dbg(adev->dev, "sienna_cichlid_i2c_write(), address = %x, bytes = %d , data: ",
-                                        (uint16_t)address, numbytes);
-
-               print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
-                              8, 1, data, numbytes, false);
-               /*
-                * According to EEPROM spec there is a MAX of 10 ms required for
-                * EEPROM to flush internal RX buffer after STOP was issued at the
-                * end of write transaction. During this time the EEPROM will not be
-                * responsive to any more commands - so wait a bit more.
-                */
-               msleep(10);
-
-       } else
-               dev_err(adev->dev, "sienna_cichlid_i2c_write- error occurred :%x", ret);
-
-       return ret;
-}
-
-static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap,
-                             struct i2c_msg *msgs, int num)
-{
-       uint32_t  i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0;
-       uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 };
-
-       for (i = 0; i < num; i++) {
-               /*
-                * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at
-                * once and hence the data needs to be spliced into chunks and sent each
-                * chunk separately
-                */
-               data_size = msgs[i].len - 2;
-               data_chunk_size = MAX_SW_I2C_COMMANDS - 2;
-               next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff);
-               data_ptr = msgs[i].buf + 2;
-
-               for (j = 0; j < data_size / data_chunk_size; j++) {
-                       /* Insert the EEPROM dest addess, bits 0-15 */
-                       data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
-                       data_chunk[1] = (next_eeprom_addr & 0xff);
-
-                       if (msgs[i].flags & I2C_M_RD) {
-                               ret = sienna_cichlid_i2c_read_data(i2c_adap,
-                                                            (uint8_t)msgs[i].addr,
-                                                            data_chunk, MAX_SW_I2C_COMMANDS);
-
-                               memcpy(data_ptr, data_chunk + 2, data_chunk_size);
-                       } else {
-
-                               memcpy(data_chunk + 2, data_ptr, data_chunk_size);
-
-                               ret = sienna_cichlid_i2c_write_data(i2c_adap,
-                                                             (uint8_t)msgs[i].addr,
-                                                             data_chunk, MAX_SW_I2C_COMMANDS);
-                       }
-
-                       if (ret) {
-                               num = -EIO;
-                               goto fail;
-                       }
-
-                       next_eeprom_addr += data_chunk_size;
-                       data_ptr += data_chunk_size;
+       for (c = i = 0; i < num_msgs; i++) {
+               if (!(msg[i].flags & I2C_M_RD)) {
+                       c += msg[i].len;
+                       continue;
                }
+               for (j = 0; j < msg[i].len; j++, c++) {
+                       SwI2cCmd_t *cmd = &res->SwI2cCmds[c];
 
-               if (data_size % data_chunk_size) {
-                       data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
-                       data_chunk[1] = (next_eeprom_addr & 0xff);
-
-                       if (msgs[i].flags & I2C_M_RD) {
-                               ret = sienna_cichlid_i2c_read_data(i2c_adap,
-                                                            (uint8_t)msgs[i].addr,
-                                                            data_chunk, (data_size % data_chunk_size) + 2);
-
-                               memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size);
-                       } else {
-                               memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size);
-
-                               ret = sienna_cichlid_i2c_write_data(i2c_adap,
-                                                             (uint8_t)msgs[i].addr,
-                                                             data_chunk, (data_size % data_chunk_size) + 2);
-                       }
-
-                       if (ret) {
-                               num = -EIO;
-                               goto fail;
-                       }
+                       msg[i].buf[j] = cmd->ReadWriteData;
                }
        }
-
+       r = num_msgs;
 fail:
-       return num;
+       kfree(req);
+       return r;
 }
 
 static u32 sienna_cichlid_i2c_func(struct i2c_adapter *adap)
@@ -3646,16 +3587,25 @@ static const struct i2c_algorithm sienna_cichlid_i2c_algo = {
        .functionality = sienna_cichlid_i2c_func,
 };
 
+static const struct i2c_adapter_quirks sienna_cichlid_i2c_control_quirks = {
+       .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR | I2C_AQ_NO_ZERO_LEN,
+       .max_read_len  = MAX_SW_I2C_COMMANDS,
+       .max_write_len = MAX_SW_I2C_COMMANDS,
+       .max_comb_1st_msg_len = 2,
+       .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
+};
+
 static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
 {
        struct amdgpu_device *adev = to_amdgpu_device(control);
        int res;
 
        control->owner = THIS_MODULE;
-       control->class = I2C_CLASS_SPD;
+       control->class = I2C_CLASS_HWMON;
        control->dev.parent = &adev->pdev->dev;
        control->algo = &sienna_cichlid_i2c_algo;
        snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
+       control->quirks = &sienna_cichlid_i2c_control_quirks;
 
        res = i2c_add_adapter(control);
        if (res)
@@ -3678,65 +3628,94 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu,
        SmuMetricsExternal_t metrics_external;
        SmuMetrics_t *metrics =
                &(metrics_external.SmuMetrics);
+       SmuMetrics_V2_t *metrics_v2 =
+               &(metrics_external.SmuMetrics_V2);
        struct amdgpu_device *adev = smu->adev;
-       uint32_t smu_version;
+       bool use_metrics_v2 = ((adev->asic_type == CHIP_SIENNA_CICHLID) &&
+               (smu->smc_fw_version >= 0x3A4300)) ? true : false;
+       uint16_t average_gfx_activity;
        int ret = 0;
 
-       ret = smu_cmn_get_metrics_table(smu,
-                                       &metrics_external,
-                                       true);
-       if (ret)
+       mutex_lock(&smu->metrics_lock);
+       ret = smu_cmn_get_metrics_table_locked(smu,
+                                              &metrics_external,
+                                              true);
+       if (ret) {
+               mutex_unlock(&smu->metrics_lock);
                return ret;
+       }
 
        smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
 
-       gpu_metrics->temperature_edge = metrics->TemperatureEdge;
-       gpu_metrics->temperature_hotspot = metrics->TemperatureHotspot;
-       gpu_metrics->temperature_mem = metrics->TemperatureMem;
-       gpu_metrics->temperature_vrgfx = metrics->TemperatureVrGfx;
-       gpu_metrics->temperature_vrsoc = metrics->TemperatureVrSoc;
-       gpu_metrics->temperature_vrmem = metrics->TemperatureVrMem0;
-
-       gpu_metrics->average_gfx_activity = metrics->AverageGfxActivity;
-       gpu_metrics->average_umc_activity = metrics->AverageUclkActivity;
-       gpu_metrics->average_mm_activity = metrics->VcnActivityPercentage;
-
-       gpu_metrics->average_socket_power = metrics->AverageSocketPower;
-       gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
-
-       if (metrics->AverageGfxActivity <= SMU_11_0_7_GFX_BUSY_THRESHOLD)
-               gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;
+       gpu_metrics->temperature_edge =
+               use_metrics_v2 ? metrics_v2->TemperatureEdge : metrics->TemperatureEdge;
+       gpu_metrics->temperature_hotspot =
+               use_metrics_v2 ? metrics_v2->TemperatureHotspot : metrics->TemperatureHotspot;
+       gpu_metrics->temperature_mem =
+               use_metrics_v2 ? metrics_v2->TemperatureMem : metrics->TemperatureMem;
+       gpu_metrics->temperature_vrgfx =
+               use_metrics_v2 ? metrics_v2->TemperatureVrGfx : metrics->TemperatureVrGfx;
+       gpu_metrics->temperature_vrsoc =
+               use_metrics_v2 ? metrics_v2->TemperatureVrSoc : metrics->TemperatureVrSoc;
+       gpu_metrics->temperature_vrmem =
+               use_metrics_v2 ? metrics_v2->TemperatureVrMem0 : metrics->TemperatureVrMem0;
+
+       gpu_metrics->average_gfx_activity =
+               use_metrics_v2 ? metrics_v2->AverageGfxActivity : metrics->AverageGfxActivity;
+       gpu_metrics->average_umc_activity =
+               use_metrics_v2 ? metrics_v2->AverageUclkActivity : metrics->AverageUclkActivity;
+       gpu_metrics->average_mm_activity =
+               use_metrics_v2 ? metrics_v2->VcnActivityPercentage : metrics->VcnActivityPercentage;
+
+       gpu_metrics->average_socket_power =
+               use_metrics_v2 ? metrics_v2->AverageSocketPower : metrics->AverageSocketPower;
+       gpu_metrics->energy_accumulator =
+               use_metrics_v2 ? metrics_v2->EnergyAccumulator : metrics->EnergyAccumulator;
+
+       average_gfx_activity = use_metrics_v2 ? metrics_v2->AverageGfxActivity : metrics->AverageGfxActivity;
+       if (average_gfx_activity <= SMU_11_0_7_GFX_BUSY_THRESHOLD)
+               gpu_metrics->average_gfxclk_frequency =
+                       use_metrics_v2 ? metrics_v2->AverageGfxclkFrequencyPostDs : metrics->AverageGfxclkFrequencyPostDs;
        else
-               gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPreDs;
-       gpu_metrics->average_uclk_frequency = metrics->AverageUclkFrequencyPostDs;
-       gpu_metrics->average_vclk0_frequency = metrics->AverageVclk0Frequency;
-       gpu_metrics->average_dclk0_frequency = metrics->AverageDclk0Frequency;
-       gpu_metrics->average_vclk1_frequency = metrics->AverageVclk1Frequency;
-       gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency;
-
-       gpu_metrics->current_gfxclk = metrics->CurrClock[PPCLK_GFXCLK];
-       gpu_metrics->current_socclk = metrics->CurrClock[PPCLK_SOCCLK];
-       gpu_metrics->current_uclk = metrics->CurrClock[PPCLK_UCLK];
-       gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0];
-       gpu_metrics->current_dclk0 = metrics->CurrClock[PPCLK_DCLK_0];
-       gpu_metrics->current_vclk1 = metrics->CurrClock[PPCLK_VCLK_1];
-       gpu_metrics->current_dclk1 = metrics->CurrClock[PPCLK_DCLK_1];
-
-       gpu_metrics->throttle_status = metrics->ThrottlerStatus;
+               gpu_metrics->average_gfxclk_frequency =
+                       use_metrics_v2 ? metrics_v2->AverageGfxclkFrequencyPreDs : metrics->AverageGfxclkFrequencyPreDs;
+       gpu_metrics->average_uclk_frequency =
+               use_metrics_v2 ? metrics_v2->AverageUclkFrequencyPostDs : metrics->AverageUclkFrequencyPostDs;
+       gpu_metrics->average_vclk0_frequency =
+               use_metrics_v2 ? metrics_v2->AverageVclk0Frequency : metrics->AverageVclk0Frequency;
+       gpu_metrics->average_dclk0_frequency =
+               use_metrics_v2 ? metrics_v2->AverageDclk0Frequency : metrics->AverageDclk0Frequency;
+       gpu_metrics->average_vclk1_frequency =
+               use_metrics_v2 ? metrics_v2->AverageVclk1Frequency : metrics->AverageVclk1Frequency;
+       gpu_metrics->average_dclk1_frequency =
+               use_metrics_v2 ? metrics_v2->AverageDclk1Frequency : metrics->AverageDclk1Frequency;
+
+       gpu_metrics->current_gfxclk =
+               use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_GFXCLK] : metrics->CurrClock[PPCLK_GFXCLK];
+       gpu_metrics->current_socclk =
+               use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_SOCCLK] : metrics->CurrClock[PPCLK_SOCCLK];
+       gpu_metrics->current_uclk =
+               use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_UCLK] : metrics->CurrClock[PPCLK_UCLK];
+       gpu_metrics->current_vclk0 =
+               use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_VCLK_0] : metrics->CurrClock[PPCLK_VCLK_0];
+       gpu_metrics->current_dclk0 =
+               use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_DCLK_0] : metrics->CurrClock[PPCLK_DCLK_0];
+       gpu_metrics->current_vclk1 =
+               use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_VCLK_1] : metrics->CurrClock[PPCLK_VCLK_1];
+       gpu_metrics->current_dclk1 =
+               use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_DCLK_1] : metrics->CurrClock[PPCLK_DCLK_1];
+
+       gpu_metrics->throttle_status = sienna_cichlid_get_throttler_status_locked(smu);
        gpu_metrics->indep_throttle_status =
-                       smu_cmn_get_indep_throttler_status(metrics->ThrottlerStatus,
+                       smu_cmn_get_indep_throttler_status(gpu_metrics->throttle_status,
                                                           sienna_cichlid_throttler_map);
 
-       gpu_metrics->current_fan_speed = metrics->CurrFanSpeed;
+       gpu_metrics->current_fan_speed = use_metrics_v2 ? metrics_v2->CurrFanSpeed : metrics->CurrFanSpeed;
 
-       ret = smu_cmn_get_smc_version(smu, NULL, &smu_version);
-       if (ret)
-               return ret;
-
-       if (((adev->asic_type == CHIP_SIENNA_CICHLID) && smu_version > 0x003A1E00) ||
-             ((adev->asic_type == CHIP_NAVY_FLOUNDER) && smu_version > 0x00410400)) {
-               gpu_metrics->pcie_link_width = metrics->PcieWidth;
-               gpu_metrics->pcie_link_speed = link_speed[metrics->PcieRate];
+       if (((adev->asic_type == CHIP_SIENNA_CICHLID) && smu->smc_fw_version > 0x003A1E00) ||
+             ((adev->asic_type == CHIP_NAVY_FLOUNDER) && smu->smc_fw_version > 0x00410400)) {
+               gpu_metrics->pcie_link_width = use_metrics_v2 ? metrics_v2->PcieWidth : metrics->PcieWidth;
+               gpu_metrics->pcie_link_speed = link_speed[use_metrics_v2 ? metrics_v2->PcieRate : metrics->PcieRate];
        } else {
                gpu_metrics->pcie_link_width =
                                smu_v11_0_get_current_pcie_link_width(smu);
@@ -3744,6 +3723,8 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu,
                                smu_v11_0_get_current_pcie_link_speed(smu);
        }
 
+       mutex_unlock(&smu->metrics_lock);
+
        gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
 
        *table = (void *)gpu_metrics;
@@ -3939,6 +3920,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
        .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
        .set_default_od_settings = sienna_cichlid_set_default_od_settings,
        .od_edit_dpm_table = sienna_cichlid_od_edit_dpm_table,
+       .restore_user_od_settings = smu_v11_0_restore_user_od_settings,
        .run_btc = sienna_cichlid_run_btc,
        .set_power_source = smu_v11_0_set_power_source,
        .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
index 0a5d46ac9ccd8b218fae70d045941c5056fedd03..b5419e8eba89b6b8a42c4b74d5e173eff8bee366 100644 (file)
@@ -266,6 +266,9 @@ int smu_v11_0_check_fw_version(struct smu_context *smu)
        case CHIP_BEIGE_GOBY:
                smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Beige_Goby;
                break;
+       case CHIP_CYAN_SKILLFISH:
+               smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Cyan_Skillfish;
+               break;
        default:
                dev_err(smu->adev->dev, "smu unsupported asic type:%d.\n", smu->adev->asic_type);
                smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_INV;
@@ -422,10 +425,20 @@ int smu_v11_0_init_smc_tables(struct smu_context *smu)
                        ret = -ENOMEM;
                        goto err3_out;
                }
+
+               smu_table->user_overdrive_table =
+                       kzalloc(tables[SMU_TABLE_OVERDRIVE].size, GFP_KERNEL);
+               if (!smu_table->user_overdrive_table) {
+                       ret = -ENOMEM;
+                       goto err4_out;
+               }
+
        }
 
        return 0;
 
+err4_out:
+       kfree(smu_table->boot_overdrive_table);
 err3_out:
        kfree(smu_table->overdrive_table);
 err2_out:
@@ -442,12 +455,14 @@ int smu_v11_0_fini_smc_tables(struct smu_context *smu)
        struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
 
        kfree(smu_table->gpu_metrics_table);
+       kfree(smu_table->user_overdrive_table);
        kfree(smu_table->boot_overdrive_table);
        kfree(smu_table->overdrive_table);
        kfree(smu_table->max_sustainable_clocks);
        kfree(smu_table->driver_pptable);
        kfree(smu_table->clocks_table);
        smu_table->gpu_metrics_table = NULL;
+       smu_table->user_overdrive_table = NULL;
        smu_table->boot_overdrive_table = NULL;
        smu_table->overdrive_table = NULL;
        smu_table->max_sustainable_clocks = NULL;
@@ -2101,3 +2116,16 @@ int smu_v11_0_deep_sleep_control(struct smu_context *smu,
 
        return ret;
 }
+
+int smu_v11_0_restore_user_od_settings(struct smu_context *smu)
+{
+       struct smu_table_context *table_context = &smu->smu_table;
+       void *user_od_table = table_context->user_overdrive_table;
+       int ret = 0;
+
+       ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)user_od_table, true);
+       if (ret)
+               dev_err(smu->adev->dev, "Failed to import overdrive table!\n");
+
+       return ret;
+}
index cb5485cf243f38295f657ecb13b3e0dcf5d48611..856eeaf293b895c759a244dde5d11cf7b6b793a8 100644 (file)
@@ -1451,197 +1451,77 @@ static bool aldebaran_is_dpm_running(struct smu_context *smu)
        return !!(feature_enabled & SMC_DPM_FEATURE);
 }
 
-static void aldebaran_fill_i2c_req(SwI2cRequest_t  *req, bool write,
-                                 uint8_t address, uint32_t numbytes,
-                                 uint8_t *data)
-{
-       int i;
-
-       req->I2CcontrollerPort = 0;
-       req->I2CSpeed = 2;
-       req->SlaveAddress = address;
-       req->NumCmds = numbytes;
-
-       for (i = 0; i < numbytes; i++) {
-               SwI2cCmd_t *cmd =  &req->SwI2cCmds[i];
-
-               /* First 2 bytes are always write for lower 2b EEPROM address */
-               if (i < 2)
-                       cmd->CmdConfig = CMDCONFIG_READWRITE_MASK;
-               else
-                       cmd->CmdConfig = write ? CMDCONFIG_READWRITE_MASK : 0;
-
-
-               /* Add RESTART for read  after address filled */
-               cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0;
-
-               /* Add STOP in the end */
-               cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0;
-
-               /* Fill with data regardless if read or write to simplify code */
-               cmd->ReadWriteData = data[i];
-       }
-}
-
-static int aldebaran_i2c_read_data(struct i2c_adapter *control,
-                                              uint8_t address,
-                                              uint8_t *data,
-                                              uint32_t numbytes)
+static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap,
+                             struct i2c_msg *msg, int num_msgs)
 {
-       uint32_t  i, ret = 0;
-       SwI2cRequest_t req;
-       struct amdgpu_device *adev = to_amdgpu_device(control);
+       struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
        struct smu_table_context *smu_table = &adev->smu.smu_table;
        struct smu_table *table = &smu_table->driver_table;
+       SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
+       int i, j, r, c;
+       u16 dir;
 
-       if (numbytes > MAX_SW_I2C_COMMANDS) {
-               dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
-                       numbytes, MAX_SW_I2C_COMMANDS);
-               return -EINVAL;
-       }
-
-       memset(&req, 0, sizeof(req));
-       aldebaran_fill_i2c_req(&req, false, address, numbytes, data);
-
-       mutex_lock(&adev->smu.mutex);
-       /* Now read data starting with that address */
-       ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req,
-                                       true);
-       mutex_unlock(&adev->smu.mutex);
-
-       if (!ret) {
-               SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr;
-
-               /* Assume SMU  fills res.SwI2cCmds[i].Data with read bytes */
-               for (i = 0; i < numbytes; i++)
-                       data[i] = res->SwI2cCmds[i].ReadWriteData;
-
-               dev_dbg(adev->dev, "aldebaran_i2c_read_data, address = %x, bytes = %d, data :",
-                                 (uint16_t)address, numbytes);
-
-               print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
-                              8, 1, data, numbytes, false);
-       } else
-               dev_err(adev->dev, "aldebaran_i2c_read_data - error occurred :%x", ret);
+       req = kzalloc(sizeof(*req), GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
 
-       return ret;
-}
+       req->I2CcontrollerPort = 0;
+       req->I2CSpeed = I2C_SPEED_FAST_400K;
+       req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
+       dir = msg[0].flags & I2C_M_RD;
+
+       for (c = i = 0; i < num_msgs; i++) {
+               for (j = 0; j < msg[i].len; j++, c++) {
+                       SwI2cCmd_t *cmd = &req->SwI2cCmds[c];
+
+                       if (!(msg[i].flags & I2C_M_RD)) {
+                               /* write */
+                               cmd->CmdConfig |= CMDCONFIG_READWRITE_MASK;
+                               cmd->ReadWriteData = msg[i].buf[j];
+                       }
 
-static int aldebaran_i2c_write_data(struct i2c_adapter *control,
-                                               uint8_t address,
-                                               uint8_t *data,
-                                               uint32_t numbytes)
-{
-       uint32_t ret;
-       SwI2cRequest_t req;
-       struct amdgpu_device *adev = to_amdgpu_device(control);
+                       if ((dir ^ msg[i].flags) & I2C_M_RD) {
+                               /* The direction changes.
+                                */
+                               dir = msg[i].flags & I2C_M_RD;
+                               cmd->CmdConfig |= CMDCONFIG_RESTART_MASK;
+                       }
 
-       if (numbytes > MAX_SW_I2C_COMMANDS) {
-               dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
-                       numbytes, MAX_SW_I2C_COMMANDS);
-               return -EINVAL;
+                       req->NumCmds++;
+
+                       /*
+                        * Insert STOP if we are at the last byte of either last
+                        * message for the transaction or the client explicitly
+                        * requires a STOP at this particular message.
+                        */
+                       if ((j == msg[i].len - 1) &&
+                           ((i == num_msgs - 1) || (msg[i].flags & I2C_M_STOP))) {
+                               cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK;
+                               cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
+                       }
+               }
        }
-
-       memset(&req, 0, sizeof(req));
-       aldebaran_fill_i2c_req(&req, true, address, numbytes, data);
-
        mutex_lock(&adev->smu.mutex);
-       ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true);
+       r = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
        mutex_unlock(&adev->smu.mutex);
+       if (r)
+               goto fail;
 
-       if (!ret) {
-               dev_dbg(adev->dev, "aldebaran_i2c_write(), address = %x, bytes = %d , data: ",
-                                        (uint16_t)address, numbytes);
-
-               print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
-                              8, 1, data, numbytes, false);
-               /*
-                * According to EEPROM spec there is a MAX of 10 ms required for
-                * EEPROM to flush internal RX buffer after STOP was issued at the
-                * end of write transaction. During this time the EEPROM will not be
-                * responsive to any more commands - so wait a bit more.
-                */
-               msleep(10);
-
-       } else
-               dev_err(adev->dev, "aldebaran_i2c_write- error occurred :%x", ret);
-
-       return ret;
-}
-
-static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap,
-                             struct i2c_msg *msgs, int num)
-{
-       uint32_t  i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0;
-       uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 };
-
-       for (i = 0; i < num; i++) {
-               /*
-                * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at
-                * once and hence the data needs to be spliced into chunks and sent each
-                * chunk separately
-                */
-               data_size = msgs[i].len - 2;
-               data_chunk_size = MAX_SW_I2C_COMMANDS - 2;
-               next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff);
-               data_ptr = msgs[i].buf + 2;
-
-               for (j = 0; j < data_size / data_chunk_size; j++) {
-                       /* Insert the EEPROM dest addess, bits 0-15 */
-                       data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
-                       data_chunk[1] = (next_eeprom_addr & 0xff);
-
-                       if (msgs[i].flags & I2C_M_RD) {
-                               ret = aldebaran_i2c_read_data(i2c_adap,
-                                                            (uint8_t)msgs[i].addr,
-                                                            data_chunk, MAX_SW_I2C_COMMANDS);
-
-                               memcpy(data_ptr, data_chunk + 2, data_chunk_size);
-                       } else {
-
-                               memcpy(data_chunk + 2, data_ptr, data_chunk_size);
-
-                               ret = aldebaran_i2c_write_data(i2c_adap,
-                                                             (uint8_t)msgs[i].addr,
-                                                             data_chunk, MAX_SW_I2C_COMMANDS);
-                       }
-
-                       if (ret) {
-                               num = -EIO;
-                               goto fail;
-                       }
-
-                       next_eeprom_addr += data_chunk_size;
-                       data_ptr += data_chunk_size;
+       for (c = i = 0; i < num_msgs; i++) {
+               if (!(msg[i].flags & I2C_M_RD)) {
+                       c += msg[i].len;
+                       continue;
                }
+               for (j = 0; j < msg[i].len; j++, c++) {
+                       SwI2cCmd_t *cmd = &res->SwI2cCmds[c];
 
-               if (data_size % data_chunk_size) {
-                       data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
-                       data_chunk[1] = (next_eeprom_addr & 0xff);
-
-                       if (msgs[i].flags & I2C_M_RD) {
-                               ret = aldebaran_i2c_read_data(i2c_adap,
-                                                            (uint8_t)msgs[i].addr,
-                                                            data_chunk, (data_size % data_chunk_size) + 2);
-
-                               memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size);
-                       } else {
-                               memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size);
-
-                               ret = aldebaran_i2c_write_data(i2c_adap,
-                                                             (uint8_t)msgs[i].addr,
-                                                             data_chunk, (data_size % data_chunk_size) + 2);
-                       }
-
-                       if (ret) {
-                               num = -EIO;
-                               goto fail;
-                       }
+                       msg[i].buf[j] = cmd->ReadWriteData;
                }
        }
-
+       r = num_msgs;
 fail:
-       return num;
+       kfree(req);
+       return r;
 }
 
 static u32 aldebaran_i2c_func(struct i2c_adapter *adap)
@@ -1655,6 +1535,14 @@ static const struct i2c_algorithm aldebaran_i2c_algo = {
        .functionality = aldebaran_i2c_func,
 };
 
+static const struct i2c_adapter_quirks aldebaran_i2c_control_quirks = {
+       .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR | I2C_AQ_NO_ZERO_LEN,
+       .max_read_len  = MAX_SW_I2C_COMMANDS,
+       .max_write_len = MAX_SW_I2C_COMMANDS,
+       .max_comb_1st_msg_len = 2,
+       .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
+};
+
 static int aldebaran_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
 {
        struct amdgpu_device *adev = to_amdgpu_device(control);
@@ -1665,6 +1553,7 @@ static int aldebaran_i2c_control_init(struct smu_context *smu, struct i2c_adapte
        control->dev.parent = &adev->pdev->dev;
        control->algo = &aldebaran_i2c_algo;
        snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
+       control->quirks = &aldebaran_i2c_control_quirks;
 
        res = i2c_add_adapter(control);
        if (res)
@@ -1764,7 +1653,9 @@ static void aldebaran_log_thermal_throttling_event(struct smu_context *smu)
 
        dev_warn(adev->dev, "WARN: GPU thermal throttling temperature reached, expect performance decrease. %s.\n",
                 log_buf);
-       kgd2kfd_smi_event_throttle(smu->adev->kfd.dev, throttler_status);
+       kgd2kfd_smi_event_throttle(smu->adev->kfd.dev,
+               smu_cmn_get_indep_throttler_status(throttler_status,
+                                                  aldebaran_throttler_map));
 }
 
 static int aldebaran_get_current_pcie_link_speed(struct smu_context *smu)
index e802f9a95f087a55c0fc336588a6242ccc86835a..415be74df28c7fe08c5a7ecaceaba929f625049b 100644 (file)
@@ -55,7 +55,7 @@
 
 #undef __SMU_DUMMY_MAP
 #define __SMU_DUMMY_MAP(type)  #type
-static const char* __smu_message_names[] = {
+static const char * const __smu_message_names[] = {
        SMU_MESSAGE_TYPES
 };
 
@@ -76,55 +76,256 @@ static void smu_cmn_read_arg(struct smu_context *smu,
        *arg = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82);
 }
 
-int smu_cmn_wait_for_response(struct smu_context *smu)
+/* Redefine the SMU error codes here.
+ *
+ * Note that these definitions are redundant and should be removed
+ * when the SMU has exported a unified header file containing these
+ * macros, which header file we can just include and use the SMU's
+ * macros. At the moment, these error codes are defined by the SMU
+ * per-ASIC unfortunately, yet we're a one driver for all ASICs.
+ */
+#define SMU_RESP_NONE           0
+#define SMU_RESP_OK             1
+#define SMU_RESP_CMD_FAIL       0xFF
+#define SMU_RESP_CMD_UNKNOWN    0xFE
+#define SMU_RESP_CMD_BAD_PREREQ 0xFD
+#define SMU_RESP_BUSY_OTHER     0xFC
+#define SMU_RESP_DEBUG_END      0xFB
+
+/**
+ * __smu_cmn_poll_stat -- poll for a status from the SMU
+ * smu: a pointer to SMU context
+ *
+ * Returns the status of the SMU, which could be,
+ *    0, the SMU is busy with your previous command;
+ *    1, execution status: success, execution result: success;
+ * 0xFF, execution status: success, execution result: failure;
+ * 0xFE, unknown command;
+ * 0xFD, valid command, but bad (command) prerequisites;
+ * 0xFC, the command was rejected as the SMU is busy;
+ * 0xFB, "SMC_Result_DebugDataDumpEnd".
+ *
+ * The values here are not defined by macros, because I'd rather we
+ * include a single header file which defines them, which is
+ * maintained by the SMU FW team, so that we're impervious to firmware
+ * changes. At the moment those values are defined in various header
+ * files, one for each ASIC, yet here we're a single ASIC-agnostic
+ * interface. Such a change can be followed-up by a subsequent patch.
+ */
+static u32 __smu_cmn_poll_stat(struct smu_context *smu)
 {
        struct amdgpu_device *adev = smu->adev;
-       uint32_t cur_value, i, timeout = adev->usec_timeout * 20;
+       int timeout = adev->usec_timeout * 20;
+       u32 reg;
 
-       for (i = 0; i < timeout; i++) {
-               cur_value = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90);
-               if ((cur_value & MP1_C2PMSG_90__CONTENT_MASK) != 0)
-                       return cur_value;
+       for ( ; timeout > 0; timeout--) {
+               reg = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90);
+               if ((reg & MP1_C2PMSG_90__CONTENT_MASK) != 0)
+                       break;
 
                udelay(1);
        }
 
-       /* timeout means wrong logic */
-       if (i == timeout)
-               return -ETIME;
-
-       return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90);
+       return reg;
 }
 
-int smu_cmn_send_msg_without_waiting(struct smu_context *smu,
-                                    uint16_t msg, uint32_t param)
+static void __smu_cmn_reg_print_error(struct smu_context *smu,
+                                     u32 reg_c2pmsg_90,
+                                     int msg_index,
+                                     u32 param,
+                                     enum smu_message_type msg)
 {
        struct amdgpu_device *adev = smu->adev;
-       int ret;
+       const char *message = smu_get_message_name(smu, msg);
 
-       ret = smu_cmn_wait_for_response(smu);
-       if (ret != 0x1) {
-               dev_err(adev->dev, "Msg issuing pre-check failed(0x%x) and "
-                      "SMU may be not in the right state!\n", ret);
-               if (ret != -ETIME)
-                       ret = -EIO;
-               return ret;
+       switch (reg_c2pmsg_90) {
+       case SMU_RESP_NONE:
+               dev_err_ratelimited(adev->dev,
+                                   "SMU: I'm not done with your previous command!");
+               break;
+       case SMU_RESP_OK:
+               /* The SMU executed the command. It completed with a
+                * successful result.
+                */
+               break;
+       case SMU_RESP_CMD_FAIL:
+               /* The SMU executed the command. It completed with an
+                * unsuccessful result.
+                */
+               break;
+       case SMU_RESP_CMD_UNKNOWN:
+               dev_err_ratelimited(adev->dev,
+                                   "SMU: unknown command: index:%d param:0x%08X message:%s",
+                                   msg_index, param, message);
+               break;
+       case SMU_RESP_CMD_BAD_PREREQ:
+               dev_err_ratelimited(adev->dev,
+                                   "SMU: valid command, bad prerequisites: index:%d param:0x%08X message:%s",
+                                   msg_index, param, message);
+               break;
+       case SMU_RESP_BUSY_OTHER:
+               dev_err_ratelimited(adev->dev,
+                                   "SMU: I'm very busy for your command: index:%d param:0x%08X message:%s",
+                                   msg_index, param, message);
+               break;
+       case SMU_RESP_DEBUG_END:
+               dev_err_ratelimited(adev->dev,
+                                   "SMU: I'm debugging!");
+               break;
+       default:
+               dev_err_ratelimited(adev->dev,
+                                   "SMU: response:0x%08X for index:%d param:0x%08X message:%s?",
+                                   reg_c2pmsg_90, msg_index, param, message);
+               break;
        }
+}
+
+static int __smu_cmn_reg2errno(struct smu_context *smu, u32 reg_c2pmsg_90)
+{
+       int res;
+
+       switch (reg_c2pmsg_90) {
+       case SMU_RESP_NONE:
+               /* The SMU is busy--still executing your command.
+                */
+               res = -ETIME;
+               break;
+       case SMU_RESP_OK:
+               res = 0;
+               break;
+       case SMU_RESP_CMD_FAIL:
+               /* Command completed successfully, but the command
+                * status was failure.
+                */
+               res = -EIO;
+               break;
+       case SMU_RESP_CMD_UNKNOWN:
+               /* Unknown command--ignored by the SMU.
+                */
+               res = -EOPNOTSUPP;
+               break;
+       case SMU_RESP_CMD_BAD_PREREQ:
+               /* Valid command--bad prerequisites.
+                */
+               res = -EINVAL;
+               break;
+       case SMU_RESP_BUSY_OTHER:
+               /* The SMU is busy with other commands. The client
+                * should retry in 10 us.
+                */
+               res = -EBUSY;
+               break;
+       default:
+               /* Unknown or debug response from the SMU.
+                */
+               res = -EREMOTEIO;
+               break;
+       }
+
+       return res;
+}
+
+static void __smu_cmn_send_msg(struct smu_context *smu,
+                              u16 msg,
+                              u32 param)
+{
+       struct amdgpu_device *adev = smu->adev;
 
        WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0);
        WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, param);
        WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg);
+}
 
-       return 0;
+/**
+ * smu_cmn_send_msg_without_waiting -- send the message; don't wait for status
+ * @smu: pointer to an SMU context
+ * @msg_index: message index
+ * @param: message parameter to send to the SMU
+ *
+ * Send a message to the SMU with the parameter passed. Do not wait
+ * for status/result of the message, thus the "without_waiting".
+ *
+ * Return 0 on success, -errno on error if we weren't able to _send_
+ * the message for some reason. See __smu_cmn_reg2errno() for details
+ * of the -errno.
+ */
+int smu_cmn_send_msg_without_waiting(struct smu_context *smu,
+                                    uint16_t msg_index,
+                                    uint32_t param)
+{
+       u32 reg;
+       int res;
+
+       if (smu->adev->no_hw_access)
+               return 0;
+
+       reg = __smu_cmn_poll_stat(smu);
+       res = __smu_cmn_reg2errno(smu, reg);
+       if (reg == SMU_RESP_NONE ||
+           reg == SMU_RESP_BUSY_OTHER ||
+           res == -EREMOTEIO)
+               goto Out;
+       __smu_cmn_send_msg(smu, msg_index, param);
+       res = 0;
+Out:
+       return res;
+}
+
+/**
+ * smu_cmn_wait_for_response -- wait for response from the SMU
+ * @smu: pointer to an SMU context
+ *
+ * Wait for status from the SMU.
+ *
+ * Return 0 on success, -errno on error, indicating the execution
+ * status and result of the message being waited for. See
+ * __smu_cmn_reg2errno() for details of the -errno.
+ */
+int smu_cmn_wait_for_response(struct smu_context *smu)
+{
+       u32 reg;
+
+       reg = __smu_cmn_poll_stat(smu);
+       return __smu_cmn_reg2errno(smu, reg);
 }
 
+/**
+ * smu_cmn_send_smc_msg_with_param -- send a message with parameter
+ * @smu: pointer to an SMU context
+ * @msg: message to send
+ * @param: parameter to send to the SMU
+ * @read_arg: pointer to u32 to return a value from the SMU back
+ *            to the caller
+ *
+ * Send the message @msg with parameter @param to the SMU, wait for
+ * completion of the command, and return back a value from the SMU in
+ * @read_arg pointer.
+ *
+ * Return 0 on success, -errno on error, if we weren't able to send
+ * the message or if the message completed with some kind of
+ * error. See __smu_cmn_reg2errno() for details of the -errno.
+ *
+ * If we weren't able to send the message to the SMU, we also print
+ * the error to the standard log.
+ *
+ * Command completion status is printed only if the -errno is
+ * -EREMOTEIO, indicating that the SMU returned back an
+ * undefined/unknown/unspecified result. All other cases are
+ * well-defined, not printed, but instead given back to the client to
+ * decide what further to do.
+ *
+ * The return value, @read_arg is read back regardless, to give back
+ * more information to the client, which on error would most likely be
+ * @param, but we can't assume that. This also eliminates more
+ * conditionals.
+ */
 int smu_cmn_send_smc_msg_with_param(struct smu_context *smu,
                                    enum smu_message_type msg,
                                    uint32_t param,
                                    uint32_t *read_arg)
 {
-       struct amdgpu_device *adev = smu->adev;
-       int ret = 0, index = 0;
+       int res, index;
+       u32 reg;
 
        if (smu->adev->no_hw_access)
                return 0;
@@ -136,31 +337,24 @@ int smu_cmn_send_smc_msg_with_param(struct smu_context *smu,
                return index == -EACCES ? 0 : index;
 
        mutex_lock(&smu->message_lock);
-       ret = smu_cmn_send_msg_without_waiting(smu, (uint16_t)index, param);
-       if (ret)
-               goto out;
-
-       ret = smu_cmn_wait_for_response(smu);
-       if (ret != 0x1) {
-               if (ret == -ETIME) {
-                       dev_err(adev->dev, "message: %15s (%d) \tparam: 0x%08x is timeout (no response)\n",
-                               smu_get_message_name(smu, msg), index, param);
-               } else {
-                       dev_err(adev->dev, "failed send message: %15s (%d) \tparam: 0x%08x response %#x\n",
-                               smu_get_message_name(smu, msg), index, param,
-                               ret);
-                       ret = -EIO;
-               }
-               goto out;
+       reg = __smu_cmn_poll_stat(smu);
+       res = __smu_cmn_reg2errno(smu, reg);
+       if (reg == SMU_RESP_NONE ||
+           reg == SMU_RESP_BUSY_OTHER ||
+           res == -EREMOTEIO) {
+               __smu_cmn_reg_print_error(smu, reg, index, param, msg);
+               goto Out;
        }
-
+       __smu_cmn_send_msg(smu, (uint16_t) index, param);
+       reg = __smu_cmn_poll_stat(smu);
+       res = __smu_cmn_reg2errno(smu, reg);
+       if (res == -EREMOTEIO)
+               __smu_cmn_reg_print_error(smu, reg, index, param, msg);
        if (read_arg)
                smu_cmn_read_arg(smu, read_arg);
-
-       ret = 0; /* 0 as driver return value */
-out:
+Out:
        mutex_unlock(&smu->message_lock);
-       return ret;
+       return res;
 }
 
 int smu_cmn_send_smc_msg(struct smu_context *smu,
index 9add5f16ff562abcde192a84c3529b529da88ea1..16993daa2ae0425a17572b02bf0a231a87559c15 100644 (file)
@@ -27,7 +27,8 @@
 
 #if defined(SWSMU_CODE_LAYER_L2) || defined(SWSMU_CODE_LAYER_L3) || defined(SWSMU_CODE_LAYER_L4)
 int smu_cmn_send_msg_without_waiting(struct smu_context *smu,
-                                    uint16_t msg, uint32_t param);
+                                    uint16_t msg_index,
+                                    uint32_t param);
 int smu_cmn_send_smc_msg_with_param(struct smu_context *smu,
                                    enum smu_message_type msg,
                                    uint32_t param,
index 0bf0ad869eb9fa125574ef374e8b350d3d6f6eba..0f66a0d9f06d03792783d6efb0013267a2918276 100644 (file)
@@ -53,14 +53,15 @@ enum amd_asic_type {
        CHIP_RENOIR,    /* 24 */
        CHIP_ALDEBARAN, /* 25 */
        CHIP_NAVI10,    /* 26 */
-       CHIP_NAVI14,    /* 27 */
-       CHIP_NAVI12,    /* 28 */
-       CHIP_SIENNA_CICHLID,    /* 29 */
-       CHIP_NAVY_FLOUNDER,     /* 30 */
-       CHIP_VANGOGH,   /* 31 */
-       CHIP_DIMGREY_CAVEFISH,  /* 32 */
-       CHIP_BEIGE_GOBY,        /* 33 */
-       CHIP_YELLOW_CARP,       /* 34 */
+       CHIP_CYAN_SKILLFISH,    /* 27 */
+       CHIP_NAVI14,    /* 28 */
+       CHIP_NAVI12,    /* 29 */
+       CHIP_SIENNA_CICHLID,    /* 30 */
+       CHIP_NAVY_FLOUNDER,     /* 31 */
+       CHIP_VANGOGH,   /* 32 */
+       CHIP_DIMGREY_CAVEFISH,  /* 33 */
+       CHIP_BEIGE_GOBY,        /* 34 */
+       CHIP_YELLOW_CARP,       /* 35 */
        CHIP_LAST,
 };