diff options
Diffstat (limited to '9001-v5.16.10-s0ix-patch-2022-02-15.patch')
-rw-r--r-- | 9001-v5.16.10-s0ix-patch-2022-02-15.patch | 680 |
1 files changed, 680 insertions, 0 deletions
diff --git a/9001-v5.16.10-s0ix-patch-2022-02-15.patch b/9001-v5.16.10-s0ix-patch-2022-02-15.patch new file mode 100644 index 000000000000..2fe5359abc13 --- /dev/null +++ b/9001-v5.16.10-s0ix-patch-2022-02-15.patch @@ -0,0 +1,680 @@ +From 271de37960d6259111bd40eb85680356f3ec7fec Mon Sep 17 00:00:00 2001 +From: Scott B <arglebargle@arglebargle.dev> +Date: Tue, 15 Feb 2022 20:28:14 -0800 +Subject: [PATCH] v5.16.10 s0ix patch 2022-02-15 + +Squashed commit of the following: + +commit cf8459de2be18aba3f364e5bff52ce379cd3c5b8 +Author: Rajib Mahapatra <rajib.mahapatra@amd.com> +Date: Thu Feb 10 19:05:07 2022 +0530 + + drm/amdgpu: skipping SDMA hw_init and hw_fini for S0ix. + + [Why] + SDMA ring buffer test failed if suspend is aborted during + S0i3 resume. + + [How] + If suspend is aborted for some reason during S0i3 resume + cycle, it follows SDMA ring test failing and errors in amdgpu + resume. For RN/CZN/Picasso, SMU saves and restores SDMA + registers during S0ix cycle. So, skipping SDMA suspend and + resume from driver solves the issue. This time, the system + is able to resume gracefully even the suspend is aborted. + + v2: add changes on sdma_v4, skipping SDMA hw_init and hw_fini. + Signed-off-by: Rajib Mahapatra <rajib.mahapatra@amd.com> + Reviewed-by: Mario Limonciello <mario.limonciello@amd.com> + Reviewed-by: Alex Deucher <alexander.deucher@amd.com> + +commit a8d24bdbc8d1d5a6f6b4f04cbb4ff3d3b7e7f3ec +Author: Mario Limonciello <mario.limonciello@amd.com> +Date: Fri Jan 28 14:35:03 2022 -0600 + + ACPI: PM: Revert "Only mark EC GPE for wakeup on Intel systems" + + Testing on various upcoming OEM systems shows commit 7b167c4cb48e ("ACPI: + PM: Only mark EC GPE for wakeup on Intel systems") was short + sighted and the symptoms were indicative of other problems. Some OEMs + do have the dedicated GPIOs for the power button but also rely upon + an interrupt to the EC SCI to let the lid work. + + The original commit showed spurious activity on Lenovo systems: + * On both Lenovo T14 and P14s the keyboard wakeup doesn't work, and + sometimes the power button event doesn't work. + + This was confirmed on my end at that time. + + However further development in the kernel showed that the issue was + actually the IRQ for the GPIO controller was also shared with the EC SCI. + This was actually fixed by commit 2d54067fcd23 ("pinctrl: amd: Fix + wakeups when IRQ is shared with SCI"). + + The original commit also showed problems with AC adapter: + * On HP 635 G7 detaching or attaching AC during suspend will cause + the system not to wakeup + * On Asus vivobook to prevent detaching AC causing resume problems + * On Lenovo 14ARE05 to prevent detaching AC causing resume problems + * On HP ENVY x360 to prevent detaching AC causing resume problems + + Detaching AC adapter causing problems appears to have been a problem + because the EC SCI went off to notify the OS of the power adapter change + but the SCI was ignored and there was no other way to wake up this system + since GPIO controller wasn't properly enabled. The wakeups were fixed by + enabling the GPIO controller in commit acd47b9f28e5 ("pinctrl: amd: Handle + wake-up interrupt"). + + I've confirmed on a variety of OEM notebooks with the following test + 1) echo 1 | sudo tee /sys/power/pm_debug_messages + 2) sudo systemctl suspend + 3) unplug AC adapter, make sure system is still asleep + 4) wake system from lid (which is provided by ACPI SCI on some of them) + 5) dmesg + a) see the EC GPE dispatched, timekeeping for X seconds (matching ~time + until AC adapter plug out) + b) see timekeeping for Y seconds until woke (matching ~time from AC + adapter until lid event) + 6) Look at /sys/kernel/debug/amd_pmc/s0ix_stats + "Time (in us) in S0i3" = X + Y - firmware processing time + + Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> + Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com> + +commit 24c381344822ce379fa17a89097253b7e37cf5f9 +Author: Mario Limonciello <mario.limonciello@amd.com> +Date: Tue Jan 11 14:00:26 2022 -0600 + + drm/amd: Warn users about potential s0ix problems + + On some OEM setups users can configure the BIOS for S3 or S2idle. + When configured to S3 users can still choose 's2idle' in the kernel by + using `/sys/power/mem_sleep`. Before commit 6dc8265f9803 ("drm/amdgpu: + always reset the asic in suspend (v2)"), the GPU would crash. Now when + configured this way, the system should resume but will use more power. + + As such, adjust the `amdpu_acpi_is_s0ix function` to warn users about + potential power consumption issues during their first attempt at + suspending. + + Reported-by: Bjoren Dasse <bjoern.daase@gmail.com> + Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1824 + Reviewed-by: Alex Deucher <alexander.deucher@amd.com> + Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> + Signed-off-by: Alex Deucher <alexander.deucher@amd.com> + +commit f2ab65214054f868a16e7dbe989262f633d3cd88 +Author: Mario Limonciello <mario.limonciello@amd.com> +Date: Thu Jan 20 11:44:39 2022 -0600 + + platform/x86: amd-pmc: Correct usage of SMU version + + Yellow carp has been outputting versions like `1093.24.0`, but this + is supposed to be 69.24.0. That is the MSB is being interpreted + incorrectly. + + The MSB is not part of the major version, but has generally been + treated that way thus far. It's actually the program, and used to + distinguish between two programs from a similar family but different + codebase. + + Link: https://patchwork.freedesktop.org/patch/469993/ + Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> + +commit 2d0b191784928ecdd8740f1930875248b7f06574 +Author: Hans de Goede <hdegoede@redhat.com> +Date: Mon Jan 17 12:26:43 2022 +0100 + + platform/x86: amd-pmc: Make amd_pmc_stb_debugfs_fops static + + amd_pmc_stb_debugfs_fops is not used outside of amd-pmc.c, make it + static. + + Cc: Sanket Goswami <Sanket.Goswami@amd.com> + Reported-by: kernel test robot <lkp@intel.com> + Signed-off-by: Hans de Goede <hdegoede@redhat.com> + Link: https://lore.kernel.org/r/20220117112644.260168-1-hdegoede@redhat.com + +commit deebcfcadd453098074c547ee10cf17dd64b1795 +Author: Sanket Goswami <Sanket.Goswami@amd.com> +Date: Tue Nov 30 16:53:18 2021 +0530 + + platform/x86: amd-pmc: Add support for AMD Smart Trace Buffer (v6) + + STB (Smart Trace Buffer), is a debug trace buffer that isolates the + failures by analyzing the last running feature of a system. This + non-intrusive way always runs in the background and stores the trace + into the SoC. + + This patch enables the STB feature by passing module param + "enable_stb=1" while loading the driver and provides mechanism to + access the STB buffer using the read and write routines. + + Co-developed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> + Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> + Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com> + +commit 6c14c1f08993eaed5b881dc46ba859de9046f3d7 +Author: Sanket Goswami <Sanket.Goswami@amd.com> +Date: Tue Nov 30 16:53:17 2021 +0530 + + platform/x86: amd-pmc: Simplify error handling and store the pci_dev in amd_pmc_dev structure + + Handle error-exits in the amd_pmc_probe() to avoid duplication and store + the root port information in amd_pmc_probe() so that the information + can be used across multiple routines. + + Suggested-by: Hans de Goede <hdegoede@redhat.com> + Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com> + +commit d92af0d67a6fd206b598c87bb52ab6d0f1815a27 +Author: Lijo Lazar <lijo.lazar@amd.com> +Date: Thu Nov 25 19:45:42 2021 +0800 + + drm/amd/pm: Add warning for unexpected PG requests + + v1: Ideally power gate/ungate requests shouldn't come when smu block is + uninitialized. Add a WARN message to check the origins if such a thing + ever happens. + + v2: Use dev_WARN to log device info (Felix/Guchun). + + Signed-off-by: Lijo Lazar <lijo.lazar@amd.com> + Reviewed-by: Guchun Chen <guchun.chen@amd.com> + Reviewed-by: Kevin Yang <kevinyang.wang@amd.com> + Signed-off-by: Alex Deucher <alexander.deucher@amd.com> + +commit 5a4e2ba710159c2bd5c3879c7b59bd35e8459224 +Author: Mario Limonciello <mario.limonciello@amd.com> +Date: Fri Sep 24 12:32:06 2021 -0500 + + ACPI: PM: s2idle: Don't report missing devices as failing constraints + + ACPI tables may have entries for devices that are not physically + present but that can be connected. These devices shouldn't cause + constraints checking to fail. + + Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> + Change-Id: I34f5ca978aab69ff0a0906191eec21649b19fe27 +--- + drivers/acpi/x86/s2idle.c | 18 ++- + drivers/gpu/drm/amd/amdgpu/amdgpu.h | 8 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 24 ++- + drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 8 + + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 6 +- + drivers/platform/x86/amd-pmc.c | 185 +++++++++++++++++++--- + 6 files changed, 213 insertions(+), 36 deletions(-) + +diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c +index 1c48358b43ba..374aa2e8203f 100644 +--- a/drivers/acpi/x86/s2idle.c ++++ b/drivers/acpi/x86/s2idle.c +@@ -309,6 +309,12 @@ static void lpi_check_constraints(void) + continue; + } + ++ if (!acpi_get_first_physical_node(adev)) { ++ acpi_handle_debug(handle, "LPI: Device is not physically present\n"); ++ lpi_constraints_table[i].handle = NULL; ++ continue; ++ } ++ + if (adev->power.state < lpi_constraints_table[i].min_dstate) + acpi_handle_info(handle, + "LPI: Constraint not met; min power state:%s current power state:%s\n", +@@ -424,15 +430,11 @@ static int lps0_device_attach(struct acpi_device *adev, + mem_sleep_current = PM_SUSPEND_TO_IDLE; + + /* +- * Some Intel based LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U don't +- * use intel-hid or intel-vbtn but require the EC GPE to be enabled while +- * suspended for certain wakeup devices to work, so mark it as wakeup-capable. +- * +- * Only enable on !AMD as enabling this universally causes problems for a number +- * of AMD based systems. ++ * Some LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U, require the ++ * EC GPE to be enabled while suspended for certain wakeup devices to ++ * work, so mark it as wakeup-capable. + */ +- if (!acpi_s2idle_vendor_amd()) +- acpi_ec_mark_gpe_for_wake(); ++ acpi_ec_mark_gpe_for_wake(); + + return 0; + } +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +index 7d67aec6f4a2..0a5a5370a200 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +@@ -1406,12 +1406,10 @@ 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_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_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, +@@ -1420,6 +1418,12 @@ static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev, + enum amdgpu_ss ss_state) { return 0; } + #endif + ++#if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND) ++bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev); ++#else ++static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; } ++#endif ++ + int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, + uint64_t addr, struct amdgpu_bo **bo, + struct amdgpu_bo_va_mapping **mapping); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +index 4811b0faafd9..b19d40751802 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +@@ -1031,6 +1031,7 @@ void amdgpu_acpi_detect(void) + } + } + ++#if IS_ENABLED(CONFIG_SUSPEND) + /** + * amdgpu_acpi_is_s0ix_active + * +@@ -1040,11 +1041,24 @@ void amdgpu_acpi_detect(void) + */ + bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) + { +-#if IS_ENABLED(CONFIG_AMD_PMC) && IS_ENABLED(CONFIG_SUSPEND) +- if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) { +- if (adev->flags & AMD_IS_APU) +- return pm_suspend_target_state == PM_SUSPEND_TO_IDLE; ++ if (!(adev->flags & AMD_IS_APU) || ++ (pm_suspend_target_state != PM_SUSPEND_TO_IDLE)) ++ return false; ++ ++ if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) { ++ dev_warn_once(adev->dev, ++ "Power consumption will be higher as BIOS has not been configured for suspend-to-idle.\n" ++ "To use suspend-to-idle change the sleep mode in BIOS setup.\n"); ++ return false; + } +-#endif ++ ++#if !IS_ENABLED(CONFIG_AMD_PMC) ++ dev_warn_once(adev->dev, ++ "Power consumption will be higher as the kernel has not been compiled with CONFIG_AMD_PMC.\n"); + return false; ++#else ++ return true; ++#endif /* CONFIG_AMD_PMC */ + } ++ ++#endif /* CONFIG_SUSPEND */ +diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +index e8e4749e9c79..f0638db57111 100644 +--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +@@ -2057,6 +2057,10 @@ static int sdma_v4_0_suspend(void *handle) + { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ++ /* SMU saves SDMA state for us */ ++ if (adev->in_s0ix) ++ return 0; ++ + return sdma_v4_0_hw_fini(adev); + } + +@@ -2064,6 +2068,10 @@ static int sdma_v4_0_resume(void *handle) + { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ++ /* SMU restores SDMA state for us */ ++ if (adev->in_s0ix) ++ return 0; ++ + return sdma_v4_0_hw_init(adev); + } + +diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +index 9d7d64fdf410..8a05b28f7365 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +@@ -277,8 +277,12 @@ static int smu_dpm_set_power_gate(void *handle, + struct smu_context *smu = handle; + int ret = 0; + +- if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) ++ if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) { ++ dev_WARN(smu->adev->dev, ++ "SMU uninitialized but power %s requested for %u!\n", ++ gate ? "gate" : "ungate", block_type); + return -EOPNOTSUPP; ++ } + + switch (block_type) { + /* +diff --git a/drivers/platform/x86/amd-pmc.c b/drivers/platform/x86/amd-pmc.c +index 230593ae5d6d..61cb1d05158e 100644 +--- a/drivers/platform/x86/amd-pmc.c ++++ b/drivers/platform/x86/amd-pmc.c +@@ -35,6 +35,12 @@ + #define AMD_PMC_SCRATCH_REG_CZN 0x94 + #define AMD_PMC_SCRATCH_REG_YC 0xD14 + ++/* STB Registers */ ++#define AMD_PMC_STB_INDEX_ADDRESS 0xF8 ++#define AMD_PMC_STB_INDEX_DATA 0xFC ++#define AMD_PMC_STB_PMI_0 0x03E30600 ++#define AMD_PMC_STB_PREDEF 0xC6000001 ++ + /* Base address of SMU for mapping physical address to virtual address */ + #define AMD_PMC_SMU_INDEX_ADDRESS 0xB8 + #define AMD_PMC_SMU_INDEX_DATA 0xBC +@@ -82,6 +88,7 @@ + #define SOC_SUBSYSTEM_IP_MAX 12 + #define DELAY_MIN_US 2000 + #define DELAY_MAX_US 3000 ++#define FIFO_SIZE 4096 + enum amd_pmc_def { + MSG_TEST = 0x01, + MSG_OS_HINT_PCO, +@@ -117,18 +124,26 @@ struct amd_pmc_dev { + u32 cpu_id; + u32 active_ips; + /* SMU version information */ +- u16 major; +- u16 minor; +- u16 rev; ++ u8 smu_program; ++ u8 major; ++ u8 minor; ++ u8 rev; + struct device *dev; ++ struct pci_dev *rdev; + struct mutex lock; /* generic mutex lock */ + #if IS_ENABLED(CONFIG_DEBUG_FS) + struct dentry *dbgfs_dir; + #endif /* CONFIG_DEBUG_FS */ + }; + ++static bool enable_stb; ++module_param(enable_stb, bool, 0644); ++MODULE_PARM_DESC(enable_stb, "Enable the STB debug mechanism"); ++ + static struct amd_pmc_dev pmc; + static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool ret); ++static int amd_pmc_write_stb(struct amd_pmc_dev *dev, u32 data); ++static int amd_pmc_read_stb(struct amd_pmc_dev *dev, u32 *buf); + + static inline u32 amd_pmc_reg_read(struct amd_pmc_dev *dev, int reg_offset) + { +@@ -166,15 +181,61 @@ static int amd_pmc_get_smu_version(struct amd_pmc_dev *dev) + if (rc) + return rc; + +- dev->major = (val >> 16) & GENMASK(15, 0); ++ dev->smu_program = (val >> 24) & GENMASK(7, 0); ++ dev->major = (val >> 16) & GENMASK(7, 0); + dev->minor = (val >> 8) & GENMASK(7, 0); + dev->rev = (val >> 0) & GENMASK(7, 0); + +- dev_dbg(dev->dev, "SMU version is %u.%u.%u\n", dev->major, dev->minor, dev->rev); ++ dev_dbg(dev->dev, "SMU program %u version is %u.%u.%u\n", ++ dev->smu_program, dev->major, dev->minor, dev->rev); + + return 0; + } + ++static int amd_pmc_stb_debugfs_open(struct inode *inode, struct file *filp) ++{ ++ struct amd_pmc_dev *dev = filp->f_inode->i_private; ++ u32 size = FIFO_SIZE * sizeof(u32); ++ u32 *buf; ++ int rc; ++ ++ buf = kzalloc(size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ rc = amd_pmc_read_stb(dev, buf); ++ if (rc) { ++ kfree(buf); ++ return rc; ++ } ++ ++ filp->private_data = buf; ++ return rc; ++} ++ ++static ssize_t amd_pmc_stb_debugfs_read(struct file *filp, char __user *buf, size_t size, ++ loff_t *pos) ++{ ++ if (!filp->private_data) ++ return -EINVAL; ++ ++ return simple_read_from_buffer(buf, size, pos, filp->private_data, ++ FIFO_SIZE * sizeof(u32)); ++} ++ ++static int amd_pmc_stb_debugfs_release(struct inode *inode, struct file *filp) ++{ ++ kfree(filp->private_data); ++ return 0; ++} ++ ++static const struct file_operations amd_pmc_stb_debugfs_fops = { ++ .owner = THIS_MODULE, ++ .open = amd_pmc_stb_debugfs_open, ++ .read = amd_pmc_stb_debugfs_read, ++ .release = amd_pmc_stb_debugfs_release, ++}; ++ + static int amd_pmc_idlemask_read(struct amd_pmc_dev *pdev, struct device *dev, + struct seq_file *s) + { +@@ -288,6 +349,10 @@ static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev) + &s0ix_stats_fops); + debugfs_create_file("amd_pmc_idlemask", 0644, dev->dbgfs_dir, dev, + &amd_pmc_idlemask_fops); ++ /* Enable STB only when the module_param is set */ ++ if (enable_stb) ++ debugfs_create_file("stb_read", 0644, dev->dbgfs_dir, dev, ++ &amd_pmc_stb_debugfs_fops); + } + #else + static inline void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev) +@@ -484,6 +549,13 @@ static int __maybe_unused amd_pmc_suspend(struct device *dev) + if (rc) + dev_err(pdev->dev, "suspend failed\n"); + ++ if (enable_stb) ++ rc = amd_pmc_write_stb(pdev, AMD_PMC_STB_PREDEF); ++ if (rc) { ++ dev_err(pdev->dev, "error writing to STB\n"); ++ return rc; ++ } ++ + return rc; + } + +@@ -504,6 +576,14 @@ static int __maybe_unused amd_pmc_resume(struct device *dev) + /* Dump the IdleMask to see the blockers */ + amd_pmc_idlemask_read(pdev, dev, NULL); + ++ /* Write data incremented by 1 to distinguish in stb_read */ ++ if (enable_stb) ++ rc = amd_pmc_write_stb(pdev, AMD_PMC_STB_PREDEF + 1); ++ if (rc) { ++ dev_err(pdev->dev, "error writing to STB\n"); ++ return rc; ++ } ++ + return 0; + } + +@@ -521,6 +601,62 @@ static const struct pci_device_id pmc_pci_ids[] = { + { } + }; + ++static int amd_pmc_write_stb(struct amd_pmc_dev *dev, u32 data) ++{ ++ int err; ++ ++ err = pci_write_config_dword(dev->rdev, AMD_PMC_STB_INDEX_ADDRESS, AMD_PMC_STB_PMI_0); ++ if (err) { ++ dev_err(dev->dev, "failed to write addr in stb: 0x%X\n", ++ AMD_PMC_STB_INDEX_ADDRESS); ++ err = pcibios_err_to_errno(err); ++ goto err_pci_dev_put; ++ } ++ ++ err = pci_write_config_dword(dev->rdev, AMD_PMC_STB_INDEX_DATA, data); ++ if (err) { ++ dev_err(dev->dev, "failed to write data in stb: 0x%X\n", ++ AMD_PMC_STB_INDEX_DATA); ++ err = pcibios_err_to_errno(err); ++ goto err_pci_dev_put; ++ } ++ ++ return 0; ++ ++err_pci_dev_put: ++ pci_dev_put(dev->rdev); ++ return err; ++} ++ ++static int amd_pmc_read_stb(struct amd_pmc_dev *dev, u32 *buf) ++{ ++ int i, err; ++ ++ err = pci_write_config_dword(dev->rdev, AMD_PMC_STB_INDEX_ADDRESS, AMD_PMC_STB_PMI_0); ++ if (err) { ++ dev_err(dev->dev, "error writing addr to stb: 0x%X\n", ++ AMD_PMC_STB_INDEX_ADDRESS); ++ err = pcibios_err_to_errno(err); ++ goto err_pci_dev_put; ++ } ++ ++ for (i = 0; i < FIFO_SIZE; i++) { ++ err = pci_read_config_dword(dev->rdev, AMD_PMC_STB_INDEX_DATA, buf++); ++ if (err) { ++ dev_err(dev->dev, "error reading data from stb: 0x%X\n", ++ AMD_PMC_STB_INDEX_DATA); ++ err = pcibios_err_to_errno(err); ++ goto err_pci_dev_put; ++ } ++ } ++ ++ return 0; ++ ++err_pci_dev_put: ++ pci_dev_put(dev->rdev); ++ return err; ++} ++ + static int amd_pmc_probe(struct platform_device *pdev) + { + struct amd_pmc_dev *dev = &pmc; +@@ -534,22 +670,23 @@ static int amd_pmc_probe(struct platform_device *pdev) + + rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0)); + if (!rdev || !pci_match_id(pmc_pci_ids, rdev)) { +- pci_dev_put(rdev); +- return -ENODEV; ++ err = -ENODEV; ++ goto err_pci_dev_put; + } + + dev->cpu_id = rdev->device; ++ dev->rdev = rdev; + err = pci_write_config_dword(rdev, AMD_PMC_SMU_INDEX_ADDRESS, AMD_PMC_BASE_ADDR_LO); + if (err) { + dev_err(dev->dev, "error writing to 0x%x\n", AMD_PMC_SMU_INDEX_ADDRESS); +- pci_dev_put(rdev); +- return pcibios_err_to_errno(err); ++ err = pcibios_err_to_errno(err); ++ goto err_pci_dev_put; + } + + err = pci_read_config_dword(rdev, AMD_PMC_SMU_INDEX_DATA, &val); + if (err) { +- pci_dev_put(rdev); +- return pcibios_err_to_errno(err); ++ err = pcibios_err_to_errno(err); ++ goto err_pci_dev_put; + } + + base_addr_lo = val & AMD_PMC_BASE_ADDR_HI_MASK; +@@ -557,24 +694,25 @@ static int amd_pmc_probe(struct platform_device *pdev) + err = pci_write_config_dword(rdev, AMD_PMC_SMU_INDEX_ADDRESS, AMD_PMC_BASE_ADDR_HI); + if (err) { + dev_err(dev->dev, "error writing to 0x%x\n", AMD_PMC_SMU_INDEX_ADDRESS); +- pci_dev_put(rdev); +- return pcibios_err_to_errno(err); ++ err = pcibios_err_to_errno(err); ++ goto err_pci_dev_put; + } + + err = pci_read_config_dword(rdev, AMD_PMC_SMU_INDEX_DATA, &val); + if (err) { +- pci_dev_put(rdev); +- return pcibios_err_to_errno(err); ++ err = pcibios_err_to_errno(err); ++ goto err_pci_dev_put; + } + + base_addr_hi = val & AMD_PMC_BASE_ADDR_LO_MASK; +- pci_dev_put(rdev); + base_addr = ((u64)base_addr_hi << 32 | base_addr_lo); + + dev->regbase = devm_ioremap(dev->dev, base_addr + AMD_PMC_BASE_ADDR_OFFSET, + AMD_PMC_MAPPING_SIZE); +- if (!dev->regbase) +- return -ENOMEM; ++ if (!dev->regbase) { ++ err = -ENOMEM; ++ goto err_pci_dev_put; ++ } + + mutex_init(&dev->lock); + +@@ -583,8 +721,10 @@ static int amd_pmc_probe(struct platform_device *pdev) + base_addr_hi = FCH_BASE_PHY_ADDR_HIGH; + fch_phys_addr = ((u64)base_addr_hi << 32 | base_addr_lo); + dev->fch_virt_addr = devm_ioremap(dev->dev, fch_phys_addr, FCH_SSC_MAPPING_SIZE); +- if (!dev->fch_virt_addr) +- return -ENOMEM; ++ if (!dev->fch_virt_addr) { ++ err = -ENOMEM; ++ goto err_pci_dev_put; ++ } + + /* Use SMU to get the s0i3 debug stats */ + err = amd_pmc_setup_smu_logging(dev); +@@ -595,6 +735,10 @@ static int amd_pmc_probe(struct platform_device *pdev) + platform_set_drvdata(pdev, dev); + amd_pmc_dbgfs_register(dev); + return 0; ++ ++err_pci_dev_put: ++ pci_dev_put(rdev); ++ return err; + } + + static int amd_pmc_remove(struct platform_device *pdev) +@@ -602,6 +746,7 @@ static int amd_pmc_remove(struct platform_device *pdev) + struct amd_pmc_dev *dev = platform_get_drvdata(pdev); + + amd_pmc_dbgfs_unregister(dev); ++ pci_dev_put(dev->rdev); + mutex_destroy(&dev->lock); + return 0; + } +-- +2.35.1 + |